服务端调用微信小程序OCR识别接口实现
一 开发环境
后端语言 java
技术工具框架 springboot
二 实现目的
本demo适用于快速服务端调用微信小程序OCR接口实现,以行驶证接口为例
包括
- 图片上传
- 调用微信小程序接口实现OCR识别
- swagger3 集成调用 去除不必要的 - - 简单实用,详细查看openapi文档
三 Demo上线
- 搭建我们的基础环境
目录结构如下
- pom文件配置
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.7.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
<version>2.1.1.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-netflix-ribbon -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
<version>2.1.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- fastjson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.59</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
- 集成swagger3
官网下载swagger,将dist目录放入Resource-static下,修改dist为swagger3
打开目录下index.html,修改为
const ui = SwaggerUIBundle({
url: "swagger.json",
dom_id: '#swagger-ui',
deepLinking: true,
presets: [
SwaggerUIBundle.presets.apis,
SwaggerUIStandalonePreset
],
plugins: [
SwaggerUIBundle.plugins.DownloadUrl
],
layout: "StandaloneLayout"
})
// End Swagger UI call region
window.ui = ui
官网打开https://petstore.swagger.io/v…,模板json,保存放到swagger3目录下,修改内容
{
"swagger": "2.0",
"info": {
"title": "小程序服务端demo",
"description": "本文档为,小程序服务端接口描述文档swagger页面",
"version": "1.0.0"
},
"tags": [
{
"name": "小程序后端服务",
"description": "此服务提供小程序访问后端系统的业务实现."
}
],
"schemes": [
"http"
],
"paths": {
"/api/vehicle/upload-vehicle": {
"post": {
"tags": [
"小程序后端服务"
],
"summary": "行驶证照片上传接口",
"description": "行驶证照片上传接口",
"operationId": "uploadFile",
"consumes": [
"multipart/form-data"
],
"produces": [
"application/json"
],
"parameters": [
{
"name": "file",
"in": "formData",
"description": "行驶证照片",
"required": true,
"type": "file"
}
],
"responses": {
"200": {
"description": "successful operation",
"schema": {
"$ref": "#/definitions/RestControllerResult"
}
}
}
}
}
},
"definitions": {
"RestControllerResult": {
"type": "object",
"properties": {
"success": {
"type": "boolean",
"description": "成功与否",
"default": false
},
"code": {
"type": "integer",
"description": "响应码",
"format": "int64"
},
"infoMsgs": {
"type": "array",
"xml": {
"name": "infoMsgs",
"wrapped": true
},
"items": {
"type": "string",
"description": "信息"
}
},
"warningMsgs": {
"type": "array",
"xml": {
"name": "warningMsgs",
"wrapped": true
},
"items": {
"type": "string",
"description": "警告信息"
}
},
"errorMsg": {
"type": "string",
"description": "错误信息"
},
"data": {
"type": "object"
}
},
"xml": {
"name": "RestControllerResult"
}
}
}
}
- application启动类添加Feign调用注解
@SpringBootApplication
@EnableFeignClients
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
- 配置全局文件 application.yml (properties修改为yml即可)
#服务配置
server:
port: 8890
compression:
enabled: true
max-http-header-size: 10000000
spring:
application:
name: ocr-demo
#外部调用
app:
vehicle: "https://api.weixin.qq.com"
至此,我们的基础环境细致的讲解完毕,且完整基础环境搭建完整,骚年们,开始代码!!!!
- 通用返回dto编写
package com.example.demo.common.dto;
import java.io.Serializable;
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;
/**
* 通用接口返回结果.
*
* @author : 小隐
* @since : 2019/8/21 9:44
*/
public class RestControllerResult<T> implements Serializable {
private static final long serialVersionUID = -3698136820012767666L;
private Boolean success;
private Integer code;
private List<String> infoMsgs = new LinkedList<>();
private List<String> warningMsgs = new LinkedList<>();
private String errorMsg;
private T data;
public RestControllerResult() {
}
public RestControllerResult(T t) {
this.data = t;
}
public Boolean getSuccess() {
return this.success;
}
public void setSuccess(Boolean success) {
this.success = success;
}
public Integer getCode() {
return this.code;
}
public void setCode(int code) {
this.code = code;
}
public List<String> getInfoMsgs() {
return this.infoMsgs;
}
public void setInfoMsgs(List<String> infoMsgs) {
this.infoMsgs = infoMsgs;
}
public List<String> getWarningMsgs() {
return this.warningMsgs;
}
public void setWarningMsgs(List<String> warningMsgs) {
this.warningMsgs = warningMsgs;
}
public String getErrorMsg() {
return this.errorMsg;
}
public void setErrorMsg(String errorMsg) {
this.errorMsg = errorMsg;
}
public T getData() {
return this.data;
}
public void setData(T data) {
this.data = data;
}
public static <T> RestControllerResult<T> success(T data) {
RestControllerResult result = new RestControllerResult(data);
result.setSuccess(true);
return result;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
} else if (o != null && this.getClass() == o.getClass()) {
RestControllerResult<?> that = (RestControllerResult) o;
return this.code.equals(that.code) && Objects.equals(this.success, that.success) && Objects
.equals(this.infoMsgs, that.infoMsgs) && Objects
.equals(this.warningMsgs, that.warningMsgs) && Objects
.equals(this.errorMsg, that.errorMsg) && Objects.equals(this.data, that.data);
} else {
return false;
}
}
@Override
public int hashCode() {
return Objects.hash(
new Object[]{this.success, this.code, this.infoMsgs, this.warningMsgs, this.errorMsg,
this.data});
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder("RestControllerResult{");
sb.append("success=").append(this.success);
sb.append(", code=").append(this.code);
sb.append(", infoMsgs=").append(this.infoMsgs);
sb.append(", warningMsgs=").append(this.warningMsgs);
sb.append(", errorMsg='").append(this.errorMsg).append('\'');
sb.append(", data=").append(this.data);
sb.append('}');
return sb.toString();
}
}
- controller层编写(分为api-controller)
api
package com.example.demo.api;
import com.example.demo.common.dto.RestControllerResult;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
/**
* 小程序请求后端系统Api.
*
* @author : 小隐
* @since : 2019/8/15 15:37
*/
@RestController
@RequestMapping("/api/vehicle")
public interface AppVehicleMiniApi {
/**
* 上传行驶证照片.
*
* @param img 图片
* @return result
*/
@PostMapping("upload-vehicle")
RestControllerResult uploadVehicle(@RequestParam("file") MultipartFile img);
}
controller
package com.example.demo.controller;
import com.alibaba.fastjson.JSONObject;
import com.example.demo.api.AppVehicleMiniApi;
import com.example.demo.common.dto.RestControllerResult;
import com.example.demo.service.AppVehicleService;
import javax.annotation.Resource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
/**
1. 小程序请求后端系统完成功能Controller.
2. 3. @author : 小隐
4. @since : 2019/8/21
*/
@RestController
public class AppVehicleMiniApiController implements AppVehicleMiniApi {
private static final Logger logger = LoggerFactory.getLogger(AppVehicleMiniApiController.class);
private static final String IMG_EMPTY = "上传照片为空";
@Resource
private AppVehicleService appVehicleService;
@Override
public RestControllerResult uploadVehicle(MultipartFile img) {
logger.info("=======>行驶证上传<=======");
RestControllerResult resultsDtoRestControllerResult = new RestControllerResult<>();
if (img.isEmpty()) {
logger.error(IMG_EMPTY);
resultsDtoRestControllerResult.setSuccess(false);
resultsDtoRestControllerResult.setCode(400);
resultsDtoRestControllerResult.setErrorMsg(IMG_EMPTY);
return resultsDtoRestControllerResult;
}
System.out.println(JSONObject.toJSONString(appVehicleService.ocrVehilce(img)));
resultsDtoRestControllerResult.setSuccess(true);
resultsDtoRestControllerResult.setCode(200);
resultsDtoRestControllerResult.setData(appVehicleService.ocrVehilce(img));
return resultsDtoRestControllerResult;
}
}
- service实现
package com.example.demo.service;
import org.springframework.web.multipart.MultipartFile;
/**
* 行驶证图片上传服务接口.
*
* @author : 小隐
* @since : 2019/8/19 15:50
*/
public interface AppVehicleService {
/**
* 识别行驶证.
*
* @param img 上传图片
* @return 识别结果
*/
Object ocrVehilce(MultipartFile img);
}
package com.example.demo.service.impl;
import com.alibaba.fastjson.JSONObject;
import com.example.demo.feign.AppVehicleFeign;
import com.example.demo.service.AppVehicleService;
import java.util.Map;
import javax.annotation.Resource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
/**
* 行驶证照片服务.
*
* @author : 小隐
* @since : 2019/8/19 18:11
*/
@Service
public class AppVehicleServiceImpl implements AppVehicleService {
private static final Logger logger = LoggerFactory.getLogger(AppVehicleServiceImpl.class);
@Resource
private AppVehicleFeign appVehicleFeign;
@Override
public Object ocrVehilce(MultipartFile img) {
Object value = appVehicleFeign.getWeiXinToken();
String s = JSONObject.toJSONString(value);
Map<String, Object> map = (Map<String, Object>)JSONObject.parse(s);
Object token = "";
if (map.get("access_token") != null) {
logger.info("最终token为" + map.get("access_token"));
token = map.get("access_token");
} else {
//返回失败结果
logger.error("微信接口服务获取token发生错误,错误代码 " + map.get("errcode"));
logger.error("微信接口服务获取token发生错误,错误信息 " + map.get("errmsg"));
}
return appVehicleFeign.ocrVehicle(img,token.toString());
}
}
- 重点戏:Feign调用实现
package com.example.demo.feign;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.multipart.MultipartFile;
/**
* 行驶证处理feign.
*
* @author : 小隐
* @since : 2019/8/20 17:03
*/
@FeignClient(value = "vehicle", fallbackFactory = AppVehicleFeignFactory.class, url = "${app.vehicle}")
public interface AppVehicleFeign {
/**
* 获取微信token.
*
* @return token
*/
@GetMapping("/cgi-bin/token?grant_type=client_credential&appid=[小程序开发id]&secret=[微信密钥]")
Object getWeiXinToken();
/**
* 识别行驶证.
*
* @param img 照片
* @param token token
* @return 识别结果
*/
@PostMapping(value = "/cv/ocr/driving?type=photo&access_token={token}",consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
Object ocrVehicle(@RequestPart(value = "file") MultipartFile img,
@PathVariable(name = "token") String token);
}
package com.example.demo.feign;
import feign.hystrix.FallbackFactory;
/**
* 行驶证feign工厂.
*
* @author : 小隐
* @since : 2019/8/20 17:10
*/
public class AppVehicleFeignFactory implements FallbackFactory<AppVehicleFeign> {
@Override
public AppVehicleFeign create(Throwable throwable) {
return null;
}
}
终于可以愉快地测试了!!!!!
启动应用,访问地址 http://localhost:8890/swagger3/index.html
干净、简洁、明了
点击上传接口,try it out,选择行驶证照片,执行
老夫手把手教学结束了!!!!
原创不易,小隐出品,转载,请注明作者、出处,谢谢大家不吝赐教!!!!!
点击查看更多内容
1人点赞
评论
共同学习,写下你的评论
评论加载中...
作者其他优质文章
正在加载中
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦