首页 > 技术文章 > JAVA项目实战-微信小程序服务端开发(二)

zhucj-java 2019-11-15 17:30 原文

本节继续分享微信小程序端,实现小程序服务端图片识别功能,包括:识别身份证,营业执照,行驶证,驾驶证,文本信息等(具体文档参考:https://developers.weixin.qq.com/miniprogram/dev/framework/)

======================================================

                                      图片识别工具类

======================================================

 

package com.sf.vsolution.hb.sfce.util.wechat.discern;

import com.alibaba.fastjson.JSON;
import com.sf.vsolution.hb.sfce.config.execption.MyRuntimeException;
import com.sf.vsolution.hb.sfce.util.FuntionUtils;
import com.sf.vsolution.hb.sfce.util.wechat.appletService.AppletServiceConstants;
import com.sf.vsolution.hb.sfce.util.wechat.discern.param.*;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * @description: 图像识别工具类
 * @author: zhucj
 * @date: 2019-10-17 9:18
 */
@Slf4j
@Component
public class DiscernImgUtil {

    @Value("${applet.appId}")
    private String appId;
    @Value("${applet.secret}")
    private String secret;
    @Value("${applet.secret.discern.imgPath}")
    private String discernPath;


    @Autowired
    private StringRedisTemplate redis;

    /**
     * 小程序端图片识别
     * @param discernRequest
     *  1:识别
     * @return
     */
    @ApiOperation(value = "小程序服务端-图片识别")
    @ApiImplicitParams({
            @ApiImplicitParam(value = "discernType",name = "识别类型(1:银行卡  2:营业执照 3:驾驶证 4:身份证 5:通用印刷体 6:行驶证)"
            ,required = true,dataType = "Integer"),
            @ApiImplicitParam(value = "msg",name = "图片的MultipartFile对象(暂时只支持传照片,未写照片连接情况)",required = true,dataType = "MultipartFile"),
            @ApiImplicitParam(value = "imgType",name = "图片识别模式 1:photo(拍照模式) 2:scan(扫描模式)",required = true,dataType = "Integer")
    })
    public R appletDiscern(DiscernRequest discernRequest){

        switch (discernRequest.getImgType()){
            case 1:
                discernRequest.setType("photo");
                break;
            case 2:
                discernRequest.setType("scan");
                break;
                default:
                    throw new DisCernImgException(SystemConstants.PARAM_INCORRECT_CODE,AppletDiscernConstant.IMG_TYPE_ERROR);
        }
        //封装图片数据
        Map mapImg = new HashMap();
        //封装参数
        Map mapParam = new HashMap<>();
        mapParam.put("type",discernRequest.getType());
        mapParam.put("access_token",getToken());
        MultipartFile msg = discernRequest.getMsg();

        mapImg.put("img",uploadFile(discernPath+ genRandomName()+".jpg",msg));
        String url = null;
        Class object = null;
        switch (discernRequest.getDiscernType()){
            case 1:
                url = DisCernImgApi.ORC_BANKCARD.getServerName();
                object =  BankCard.class;
                break;
            case 2:
                url = DisCernImgApi.ORC_BIZLICENSE.getServerName();
                object = Bizlicense.class;
                break;
            case 3:
                url = DisCernImgApi.ORC_DRIVINGLICENSE.getServerName();
                object = DriverLicense.class;
                break;
            case 4:
                url = DisCernImgApi.ORC_IDCARD.getServerName();
                object = IDCard.class;
                break;
            case 5:
                url = DisCernImgApi.ORC_COMM.getServerName();
                object = PrintedText.class;
                break;
            case 6:
                url = DisCernImgApi.ORC_DRIVING.getServerName();
                break;
            default:
                throw new DisCernImgException(SystemConstants.PARAM_INCORRECT_CODE,AppletDiscernConstant.DIECERN_TYPE_ERROR);
        }
        String result = HttpClientUtil.postFormData(url, mapParam, mapImg, "image/png");
        log.info("响应信息内容:{}",result);
        DiscernCommonResponse discernCommonResponse = JSON.parseObject(result, DiscernCommonResponse.class);
        if (Objects.equals(AppletDiscernConstant.SUCCESS, discernCommonResponse.getErrcode())){
            return R.ok(JSON.parseObject(result,object));
        }else {
            log.error("获取照片信息失败:{}", discernCommonResponse.getErrcode());
            return R.ok(discernCommonResponse.getErrmsg());
        }

    }





    /**
     * 小程序授权
     * @return accessToken
     * @throws  DisCernImgException
     */
    public String getToken(){
        //先从缓存中判断是否存在
        String redisString = redis.opsForValue().get(AppletDiscernConstant.ACCESS_TOKEN);
        if (Objects.nonNull(redisString)){
            return redisString;
        }
        String reqUrl = AppletServiceConstants.ACCESS_TOKEN_API;
        Map map = new HashMap();
        map.put("grant_type","client_credential");
        map.put("appid",appId);
        map.put("secret",secret);
        String result = HttpClientUtil.doGet(reqUrl, map);
        AuthAccessTokenResponse auth = JSON.parseObject(result, AuthAccessTokenResponse.class);
        //判断errcode ==0 即请求成功
        if (Objects.equals(auth.getErrcode(),AppletServiceConstants.SUCCESS_CODE)){
            log.info("获取的accessToken值:{}",auth.getAccess_token());
            //将accessToken存入到redis 设置过期时间
            redis.opsForValue().set(AppletServiceConstants.ACCESS_TOKEN,auth.getAccess_token(),AppletServiceConstants.EXPIRES_IN, TimeUnit.SECONDS);
            return auth.getAccess_token();
        }else {
            log.error("小程序授权失败返回错误码:{},错误信息:{}",auth.getErrcode(),auth.getErrmsg());
            throw new DisCernImgException(SystemConstants.SERVER_ERROR_CODE,AppletDiscernConstant.ACCESS_TOKRN_ERROR);
        }


    }

    /**
     * 上传文件到本地服务器磁盘
     * @param fileName 上传文件路径名称
     *                 例如: /static/upload/121321321.jpg
     *                      E:/upload/img/12013212.jpg
     * @param file
     * @return
     */
    public static String uploadFile(String fileName, MultipartFile file){

        //服务器端保存的文件对象
        File serverFile= new File(fileName);
        try {
            //判断文件是否已经存在
            if (serverFile.exists()) {
                throw new DisCernImgException(SystemConstants.PARAM_INCORRECT_CODE,"文件已存在");
            }
            //判断文件父目录是否存在
            if (!serverFile.getParentFile().exists()) {
                serverFile.getParentFile().mkdir();
            }
            //将上传的文件写入到服务器端文件内
            file.transferTo(serverFile);
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
        return fileName;
    }

public static String genRandomName() {
//取当前时间的长整形值包含毫秒
long millis = System.currentTimeMillis();
//加上三位随机数
Random random = new Random();
int end3 = random.nextInt(999);
//如果不足三位前面补0
String str = millis + String.format("%03d", end3);

return str;
}
}

=================================================

                   封装类,常量类,异常类

=================================================

package com.sf.vsolution.hb.sfce.util.wechat.discern;

import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

import javax.activation.MimetypesFileTypeMap;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URI;
import java.net.URL;
import java.util.Iterator;
import java.util.Map;

/**
 * @description: get/post请求工具类
 * @author: zhucj
 * @date: 2019-04-26 10:10
 */
@Slf4j
public class HttpClientUtil {

    /**
     * 发送get请求
     * @param url
     * @param param
     * @return
     */
    public static String doGet(String url, Map<String, String> param) {
        log.info("GET请求地址:{},请求参数内容:{}",url, JSON.toJSON(param));
        // 创建Httpclient对象
        CloseableHttpClient httpclient = HttpClients.createDefault();

        String resultString = "";
        CloseableHttpResponse response = null;
        try {
            // 创建uri
            URIBuilder builder = new URIBuilder(url);
            if (param != null) {
                for (String key : param.keySet()) {
                    builder.addParameter(key, param.get(key));
                }
            }
            URI uri = builder.build();
            // 创建http GET请求
            HttpGet httpGet = new HttpGet(uri);

            // 执行请求
            response = httpclient.execute(httpGet);
            // 判断返回状态是否为200
            if (response.getStatusLine().getStatusCode() == 200) {
                resultString = EntityUtils.toString(response.getEntity(), "UTF-8");
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error("网络出现异常:{}",e.getMessage());
        } finally {
            try {
                if (response != null) {
                    response.close();
                }
                httpclient.close();
            } catch (IOException e) {
                e.printStackTrace();
                log.error("IO出现异常:{}",e.getMessage());
            }
        }
        log.info("GET响应参数:{}",resultString);
        return resultString;
    }

    /**
     * 发送post请求
     * @param url
     * @param param
     * @return
     */
    public static String doPostParam(String url, Map<String, String> param) {
        log.info("GET请求地址:{},请求参数内容:{}",url, JSON.toJSON(param));
        // 创建Httpclient对象
        CloseableHttpClient httpclient = HttpClients.createDefault();

        String resultString = "";
        CloseableHttpResponse response = null;
        try {
            // 创建uri
            URIBuilder builder = new URIBuilder(url);
            if (param != null) {
                for (String key : param.keySet()) {
                    builder.addParameter(key, param.get(key));
                }
            }
            URI uri = builder.build();

            // 创建http GET请求
            HttpPost httpPost = new HttpPost(uri);

            // 执行请求
            response = httpclient.execute(httpPost);
            // 判断返回状态是否为200
            if (response.getStatusLine().getStatusCode() == 200) {
                resultString = EntityUtils.toString(response.getEntity(), "UTF-8");
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error("网络出现异常:{}",e.getMessage());
        } finally {
            try {
                if (response != null) {
                    response.close();
                }
                httpclient.close();
            } catch (IOException e) {
                e.printStackTrace();
                log.error("IO出现异常:{}",e.getMessage());
            }
        }
        log.info("GET响应参数:{}",resultString);
        return resultString;
    }

    /**
     * 发post请求 传入xml/json字符串
     * @param url
     * @param json
     * @return
     */
    public static String doPostJson(String url, String json) {
        log.info("POST请求地址:{},请求参数内容:{}",url,json);
        // 创建Httpclient对象
        CloseableHttpClient httpClient = HttpClients.createDefault();
        CloseableHttpResponse response = null;
        String resultString = "";
        try {
            // 创建Http Post请求
            HttpPost httpPost = new HttpPost(url);
            // 创建请求内容
            StringEntity entity = new StringEntity(json, ContentType.APPLICATION_JSON);
            httpPost.setEntity(entity);
            // 执行http请求
            response = httpClient.execute(httpPost);
            resultString = EntityUtils.toString(response.getEntity(), "utf-8");
        } catch (Exception e) {
            e.printStackTrace();
            log.error("网络出现异常:{}",e.getMessage());
        } finally {
            try {
                response.close();
            } catch (IOException e) {
                e.printStackTrace();
                log.error("IO出现异常:{}",e.getMessage());
            }
        }
        log.info("POST响应参数:{}",resultString);
        return resultString;
    }

    /**
     * 发送文件和参数
     * @param urlStr
     * @param textMap
     * @param fileMap
     * @param contentType 没有传入文件类型默认采用application/octet-stream
     * contentType非空采用filename匹配默认的图片类型
     * @return 返回response数据
     */
    @SuppressWarnings("rawtypes")

    public static String postFormData(String urlStr, Map<String, String> textMap,
                                    Map<String, String> fileMap,String contentType) {
        String res = "";
        HttpURLConnection conn = null;
        // boundary就是request头和上传文件内容的分隔符
        String BOUNDARY = "---------------------------123821742118716";
        try {
            URL url = new URL(urlStr);
            conn = (HttpURLConnection) url.openConnection();
            conn.setConnectTimeout(5000);
            conn.setReadTimeout(30000);
            conn.setDoOutput(true);
            conn.setDoInput(true);
            conn.setUseCaches(false);
            conn.setRequestMethod("POST");
            conn.setRequestProperty("Connection", "Keep-Alive");
            conn.setRequestProperty("User-Agent",
                    "Mozilla/5.0 (Windows; U; Windows NT 6.1; zh-CN; rv:1.9.2.6)");
            conn.setRequestProperty("Content-Type",
                    "multipart/form-data; boundary=" + BOUNDARY);
            OutputStream out = new DataOutputStream(conn.getOutputStream());
            // text
            if (textMap != null) {
                StringBuffer strBuf = new StringBuffer();
                Iterator iter = textMap.entrySet().iterator();
                while (iter.hasNext()) {
                    Map.Entry entry = (Map.Entry) iter.next();
                    String inputName = (String) entry.getKey();
                    String inputValue = (String) entry.getValue();
                    if (inputValue == null) {
                        continue;
                    }
                    strBuf.append("\r\n").append("--").append(BOUNDARY)
                            .append("\r\n");
                    strBuf.append("Content-Disposition: form-data; name=\""
                            + inputName + "\"\r\n\r\n");
                    strBuf.append(inputValue);
                }
                out.write(strBuf.toString().getBytes());
            }
            // file
            if (fileMap != null) {
                Iterator iter = fileMap.entrySet().iterator();
                while (iter.hasNext()) {
                    Map.Entry entry = (Map.Entry) iter.next();
                    String inputName = (String) entry.getKey();
                    String inputValue = (String) entry.getValue();
                    if (inputValue == null) {
                        continue;
                    }
                    File file = new File(inputValue);
                    String filename = file.getName();

                    //没有传入文件类型,同时根据文件获取不到类型,默认采用application/octet-stream
                    contentType = new MimetypesFileTypeMap().getContentType(file);
                    //contentType非空采用filename匹配默认的图片类型
                    if(!"".equals(contentType)){
                        if (filename.endsWith(".png")) {
                            contentType = "image/png";
                        }else if (filename.endsWith(".jpg") || filename.endsWith(".jpeg") || filename.endsWith(".jpe")) {
                            contentType = "image/jpeg";
                        }else if (filename.endsWith(".gif")) {
                            contentType = "image/gif";
                        }else if (filename.endsWith(".ico")) {
                            contentType = "image/image/x-icon";
                        }
                    }
                    if (contentType == null || "".equals(contentType)) {
                        contentType = "application/octet-stream";
                    }
                    StringBuffer strBuf = new StringBuffer();
                    strBuf.append("\r\n").append("--").append(BOUNDARY)
                            .append("\r\n");
                    strBuf.append("Content-Disposition: form-data; name=\""
                            + inputName + "\"; filename=\"" + filename
                            + "\"\r\n");
                    strBuf.append("Content-Type:" + contentType + "\r\n\r\n");
                    out.write(strBuf.toString().getBytes());
                    DataInputStream in = new DataInputStream(
                            new FileInputStream(file));
                    int bytes = 0;
                    byte[] bufferOut = new byte[1024];
                    while ((bytes = in.read(bufferOut)) != -1) {
                        out.write(bufferOut, 0, bytes);
                    }
                    in.close();
                }
            }
            byte[] endData = ("\r\n--" + BOUNDARY + "--\r\n").getBytes();
            out.write(endData);
            out.flush();
            out.close();
            // 读取返回数据
            StringBuffer strBuf = new StringBuffer();
            BufferedReader reader = new BufferedReader(new InputStreamReader(
                    conn.getInputStream()));
            String line = null;
            while ((line = reader.readLine()) != null) {
                strBuf.append(line).append("\n");
            }
            res = strBuf.toString();
            reader.close();
            reader = null;
        } catch (Exception e) {
            System.out.println("发送POST请求出错。" + urlStr);
            e.printStackTrace();
        } finally {
            if (conn != null) {
                conn.disconnect();
                conn = null;
            }
        }
        return res;
    }
}
package com.sf.vsolution.hb.sfce.util.wechat.discern;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.ToString;

import java.io.Serializable;

/**
 * 返回类型
 * @author choleece
 * @date 2018/9/27
 */
@ApiModel
@ToString
public class R<T> implements Serializable {

    private static final long serialVersionUID = -6287952131441663819L;

    /**
     * 编码
     */
    @ApiModelProperty(value = "响应码", example = "200")
    private int code = 200;

    /**
     * 成功标志
     */
    @ApiModelProperty(value = "成功标志", example = "true")
    private Boolean success;

    /**
     * 返回消息
     */
    @ApiModelProperty(value = "返回消息说明", example = "操作成功")
    private String msg="操作成功";

    /**
     * 返回数据
     */
    @ApiModelProperty(value = "返回数据")
    private T data;

    /**
     * 创建实例
     * @return
     */
    public static R instance() {
        return new R();
    }

    public int getCode() {
        return code;
    }

    public R setCode(int code) {
        this.code = code;
        return this;
    }

    public Boolean getSuccess() {
        return success;
    }

    public R setSuccess(Boolean success) {
        this.success = success;
        return this;
    }

    public String getMsg() {
        return msg;
    }

    public R setMsg(String msg) {
        this.msg = msg;
        return this;
    }

    public T getData() {
        return data;
    }
    public R setData(T data) {
        this.data = data;
        return this;
    }

    public static R ok() {
        return R.instance().setSuccess(true);
    }

    public static R ok(Object data) {
        return ok().setData(data);
    }

    public static R ok(Object data, String msg) {
        return ok(data).setMsg(msg);
    }

    public static R error() {
        return R.instance().setSuccess(false);
    }

    public static R error(String msg) {
        return error().setMsg(msg);
    }

    /**
     * 无参
     */
    public R() {
    }

    public R(int code, String msg) {
        this.code = code;
        this.msg = msg;
    }

    public R(int code, T data){
        this.code = code;
        this.data = data;
    }

    /**
     * 有全参
     * @param code
     * @param msg
     * @param data
     * @param success
     */
    public R(int code, String msg, T data, Boolean success) {
        this.code = code;
        this.msg = msg;
        this.data = data;
        this.success = success;
    }

    /**
     * 有参
     * @param code
     * @param msg
     * @param data
     */
    public R(int code, String msg, T data) {
        this.code = code;
        this.msg = msg;
        this.data = data;
    }

}
package com.sf.vsolution.hb.sfce.util.wechat.discern;

/**
 * @description: 图片识别异常
 * @author: zhucj
 * @date: 2019-10-17 10:16
 */
public class DisCernImgException extends RuntimeException  {


    private Integer errcode;

    private String errmsg;


    public DisCernImgException(Integer errcode, String errmsg) {
        this.errcode = errcode;
        this.errmsg = errmsg;
    }

    public Integer getErrcode() {
        return errcode;
    }

    public void setErrcode(Integer errcode) {
        this.errcode = errcode;
    }

    public String getErrmsg() {
        return errmsg;
    }

    public void setErrmsg(String errmsg) {
        this.errmsg = errmsg;
    }
}
package com.sf.vsolution.hb.sfce.util.wechat.discern.param;

/**
 * @description: 小程序API常量
 * @author: zhucj
 * @date: 2019-09-17 18:25
 */
public class AppletDiscernConstant {


    /**
     * 小程序登录API
     */
    public static final String AUTH_CODE_API = "https://api.weixin.qq.com/sns/jscode2session";

    /**
     * accessToken授权API
     */
    public static final String ACCESS_TOKEN_API = "https://api.weixin.qq.com/cgi-bin/token";
    /**
     * 客服消息API
     */
    public static final String  MESSAGE_SEND_API = "https://api.weixin.qq.com/cgi-bin/message/custom/send";


    /**
     * accessToken缓存key
     */
    public static final String ACCESS_TOKEN = "ACCESS_TOKEN";

    public static final Integer EXPIRES_IN  = 7000;


    //TODO: 异常信息状态


    public static final String ACCESS_TOKRN_ERROR = "小程序授权获取accessToken失败";
    public static final String DIECERN_TYPE_ERROR = "diecernType传参格式不支持";
    public static final String IMG_TYPE_ERROR = "imgType传参格式不支持";

    public static final String SUCCESS = "0";
}
package com.sf.vsolution.hb.sfce.util.wechat.discern.param;

import com.sf.vsolution.hb.sfce.util.wechat.appletService.param.CommonResponse;
import lombok.*;

/**
 * @description: 小程序获取AccessToken返回参数
 * @author: zhucj
 * @date: 2019-11-14 16:43
 */
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class AuthAccessTokenResponse extends CommonResponse {


    /**
     * 获取到的凭证
     */
    private String access_token;

    /**
     * 凭证有效时间,单位:秒。目前是7200秒之内的值。
     */
    private Integer expires_in;
}
package com.sf.vsolution.hb.sfce.util.wechat.discern.param;

import lombok.Data;

/**
 * @description: 识别银行卡号返回参数
 * @author: zhucj
 * @date: 2019-10-17 12:55
 */
@Data
public class BankCard extends DiscernCommonResponse {

    /**
     * 银行卡号
     */
    private String number;
}
package com.sf.vsolution.hb.sfce.util.wechat.discern.param;

import lombok.Data;

/**
 * @description: 识别营业执照返回参数
 * @author: zhucj
 * @date: 2019-10-17 12:57
 */
@Data
public class Bizlicense extends DiscernCommonResponse {

    /**
     * 注册号
     */
    private String reg_num;

    /**
     * 编号
     */
    private String serial;

    /**
     * 法定代表人姓名
     */
    private String legal_representative;

    /**
     * 企业名称
     */
    private String enterprise_name;

    /**
     * 组成形式
     */
    private String type_of_organization;

    /**
     * 经营场所/企业住所
     */
    private String address;

    /**
     * 公司类型
     */
    private String type_of_enterprise;

    /**
     * 经营范围
     */
    private String business_scope;

    /**
     * 注册资本
     */
    private String registered_capital;

    /**
     * 实收资本
     */
    private String paid_in_capital;

    /**
     * 营业期限
     */
    private String valid_period;


    /**
     * 注册日期/成立日期
     */
    private String registered_date;



}
package com.sf.vsolution.hb.sfce.util.wechat.discern.param;

import lombok.*;

/**
 * @description: 通用返回参数
 * @author:zhucj
 * @date: 2019-10-17 9:25
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
@ToString
public class DiscernCommonResponse {

    /**
     * 响应编码
     */
    private String errcode;

    /**
     * 响应消息
     */
    private String errmsg;
}
package com.sf.vsolution.hb.sfce.util.wechat.discern.param;

/**
 * @description: 图片识别常量
 * @author: zhucj
 * @date: 2019-10-17 9:48
 */
public class DisCernConstant {


    /**
     * 共用接口
     */
    public static final String  WX_DISCERN_SERVER_API = "https://api.weixin.qq.com";

    /**
     * 小程序的银行卡 OCR 识别
     */
    public static final String  WX_BANKCARD_DISCERN_SERVER_NAME = "/cv/ocr/bankcard";

    /**
     * 小程序的营业执照 OCR 识别
     */
    public static final String  WX_BUCINESS_DISCERN_SERVER_NAME = "/cv/ocr/bizlicense";

    /**
     * 小程序的驾驶证 OCR 识别
     */
    public static final String  WX_DRIVER_DISCERN_SERVER_NAME = "/cv/ocr/drivinglicense";

    /**
     * 小程序的身份证 OCR 识别
     */
    public static final String  WX_IDCARD_DISCERN_SERVER_NAME = "/cv/ocr/idcard";

    /**
     * 小程序的通用印刷体 OCR 识别
     */
    public static final String  WX_PRINTED_DISCERN_SERVER_NAME = "/cv/ocr/comm";

    /**
     * 小程序的行驶证 OCR 识别
     */
    public static final String  WX_DRIVING_DISCERN_SERVER_NAME = "/cv/ocr/driving";

}
package com.sf.vsolution.hb.sfce.util.wechat.discern.param;

import com.sf.vsolution.hb.sfce.util.wechat.discern.param.DisCernConstant;

/**
 * @description: 图片识别API
 * @author: zhucj
 * @date: 2019-10-17 9:44
 */
public enum  DisCernImgApi {
    /**
     * 小程序端识别
     */
    ORC_BANKCARD(1, DisCernConstant.WX_DISCERN_SERVER_API+DisCernConstant.WX_BANKCARD_DISCERN_SERVER_NAME),
    ORC_BIZLICENSE(2,DisCernConstant.WX_DISCERN_SERVER_API+DisCernConstant.WX_BUCINESS_DISCERN_SERVER_NAME),
    ORC_DRIVINGLICENSE(3,DisCernConstant.WX_DISCERN_SERVER_API+DisCernConstant.WX_DRIVER_DISCERN_SERVER_NAME),
    ORC_IDCARD(4,DisCernConstant.WX_DISCERN_SERVER_API+DisCernConstant.WX_IDCARD_DISCERN_SERVER_NAME),
    ORC_COMM(5,DisCernConstant.WX_DISCERN_SERVER_API+DisCernConstant.WX_PRINTED_DISCERN_SERVER_NAME),
    ORC_DRIVING(6,DisCernConstant.WX_DISCERN_SERVER_API+DisCernConstant.WX_DRIVING_DISCERN_SERVER_NAME)
    ;

    private int discernType;

    private String  serverName;

    DisCernImgApi(int discernType, String serverName) {
        this.discernType = discernType;
        this.serverName = serverName;
    }

    public int getDiscernType() {
        return discernType;
    }

    public void setDiscernType(int discernType) {
        this.discernType = discernType;
    }

    public String getServerName() {
        return serverName;
    }

    public void setServerName(String serverName) {
        this.serverName = serverName;
    }
}
package com.sf.vsolution.hb.sfce.util.wechat.discern.param;

import lombok.Builder;
import lombok.Data;
import org.springframework.web.multipart.MultipartFile;

/**
 * @description: 识别请求信息
 * @author: zhucj
 * @date: 2019-10-17 9:31
 */
@Data
@Builder
public class DiscernRequest {

    /**
     * 识别类型
     * 1:银行卡  2:营业执照 3:驾驶证 4:身份证 5:通用印刷体 6:行驶证
     */
    private Integer discernType;

    /**
     * 图片识别模式 1:photo(拍照模式) 2:scan(扫描模式)
     */
    private Integer imgType;

    /**
     * form-data 中媒体文件标识,有filename、filelength、content-type等信息,传这个则不用传 img_url
     */
    private MultipartFile msg;


    private String type;
}
package com.sf.vsolution.hb.sfce.util.wechat.discern.param;

import lombok.Data;

/**
 * @description: 识别驾驶证返回参数
 * @author: zhucj
 * @date: 2019-11-15 13:51
 */
@Data
public class DriverLicense extends DiscernCommonResponse {

    /**
     * 证号
     */
    private String id_num;

    /**
     * 姓名
     */
    private String name;
    /**
     *性别
     */
    private String sex;

    /**
     * address
     */
    private String address;

    /**
     * 出生日期
     */
    private String birth_date;

    /**
     * 初次领证日期
     */
    private String issue_date;

    /**
     * 准驾车型
     */
    private String car_class;

    /**
     * 有效期限起始日
     */
    private String valid_from;

    /**
     * 有效期限终止日
     */
    private String valid_to;

    /**
     * 印章文构
     */
    private String official_seal;
}
package com.sf.vsolution.hb.sfce.util.wechat.discern.param;

import lombok.Data;

/**
 * @description: 身份证识别返回参数
 * @author: zhucj
 * @date: 2019-11-15 14:02
 */
@Data
public class IDCard extends DiscernCommonResponse {

    /**
     * 姓名
     */
    private String name;

    /**
     * 身份证号
     */
    private String id;

    /**
     * 地址
     */
    private String addr;

    /**
     * 性别
     */
    private String gender;

    /**
     * 民族
     */
    private String nationality;

    /**
     * 正面或背面,Front / Back
     */
    private String type;

    /**
     * 有效期(type = back 才有)
     */
    private String validDate;
}
package com.sf.vsolution.hb.sfce.util.wechat.discern.param;

import lombok.Data;

/**
 * @description:
 * @author:zhucj
 * @date: 2019-10-17 15:22
 */
@Data
public class PrintedText extends DiscernCommonResponse {

    private String items;

    private String img_size;
}
package com.sf.vsolution.hb.sfce.util.wechat.discern.param;

/**
 * @ClassName SystemConstants
 * @Description 常量字段
 * @Author zhucj
 * @Date 2019/5/7 11:13
 * @Version 1.0
 **/
public class SystemConstants {


    /** 传参不规范,code:400*/
    public static final Integer PARAM_INCORRECT_CODE = 400;

    /** 成功,code:200*/
    public static final Integer SUCCESS_CODE = 200;

    /** 服务内部调用失败,code:500*/
    public static final Integer SERVER_ERROR_CODE = 500;

    /** 登录失效,code:401*/
    public static final Integer AUTH_FAIL_CODE = 401;

    /** 无对应接口权限,code:402*/
    public static final Integer HAVE_NOT_PERMISSION_CODE = 402;

    /** 操作无记录,code:403*/
    public static final Integer NO_RECORD_OPERATION = 403;


}
#小程序参数
applet:
  appId: *****
  secret: *****
  discern:
   #识别图片保存地址
    imgPath: E:/upload/img/

 

       <!-- lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.2</version>
            <scope>provided</scope>
        </dependency>

       <!--htttpclient依赖-->
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
            <version>4.5.5</version>
        </dependency>

    <!-- swagger API -->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>2.6.0</version>
        </dependency>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>2.6.0</version>
        </dependency>

 

推荐阅读