1.完成car下面的所有接口,使用的百度云接口

This commit is contained in:
jiangtd 2026-05-19 17:31:55 +08:00
parent 001fe17de3
commit 7d8d4d293d
12 changed files with 239 additions and 183 deletions

View File

@ -0,0 +1,34 @@
package com.heyu.api.baidu.handle.financial;
import com.heyu.api.data.annotation.CustomPath;
import com.heyu.api.baidu.BaiduBaseHandle;
import com.heyu.api.baidu.request.financial.BTrainTicketRequest;
import com.heyu.api.baidu.response.financial.BTrainTicketResp;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
/**
* https://console.bce.baidu.com/support/#/api?product=AI&project=文字识别&parent=财务票据OCR&api=rest%2F2.0%2Focr%2Fv1%2Ftrain_ticket&method=post
*
* 火车票识别
*/
@Component
@Slf4j
@CustomPath("trainTicket")
public class BTrainTicketHandle extends BaiduBaseHandle<BTrainTicketRequest, BTrainTicketResp> {
@Override
public String getUri() {
return "/rest/2.0/ocr/v1/train_ticket";
}
@Override
public String check(BTrainTicketRequest request) {
return checkImageUri(request);
}
@Override
public String getContent(BTrainTicketRequest request) {
return getImageContent(request).toString();
}
}

View File

@ -0,0 +1,12 @@
package com.heyu.api.baidu.request.financial;
import com.heyu.api.baidu.request.BaiduImageUrlRequest;
/**
* https://console.bce.baidu.com/support/#/api?product=AI&project=文字识别&parent=财务票据OCR&api=rest%2F2.0%2Focr%2Fv1%2Ftrain_ticket&method=post
*
* 火车票识别
*/
public class BTrainTicketRequest extends BaiduImageUrlRequest {
}

View File

@ -35,7 +35,7 @@ public class ANumbersResp extends BBaseResp {
@JsonProperty("log_id")
private Integer logId;
private Long logId;
@JsonProperty("words_result")
private List<WordsResultDTO> wordsResult;
@JsonProperty("words_result_num")

View File

@ -18,7 +18,7 @@ public class BDocConvertResp extends BBaseResp {
@JsonProperty("success")
private Boolean success;
@JsonProperty("log_id")
private Integer logId;
private Long logId;
@JsonProperty("result")
private ResultDTO result;
@JsonProperty("code")

View File

@ -18,7 +18,7 @@ public class BFerryTicketResp {
@JsonProperty("log_id")
private Integer logId;
private Long logId;
@JsonProperty("words_result_num")
private Integer wordsResultNum;
@JsonProperty("words_result")

View File

@ -17,7 +17,7 @@ public class BTaxiReceiptResp extends BBaseResp {
@JsonProperty("log_id")
private Integer logId;
private Long logId;
@JsonProperty("words_result_num")
private Integer wordsResultNum;
@JsonProperty("words_result")

View File

@ -19,7 +19,7 @@ public class BVinCodeResp extends BBaseResp {
@JsonProperty("log_id")
private Integer logId;
private Long logId;
@JsonProperty("words_result")
private List<WordsResultDTO> wordsResult;
@JsonProperty("words_result_num")

View File

@ -1,9 +1,5 @@
package com.heyu.api.controller.car;
import com.aliyun.ocr20191230.models.RecognizeTaxiInvoiceResponse;
import com.aliyun.ocr20191230.models.RecognizeTaxiInvoiceResponseBody;
import com.heyu.api.alibaba.handle.common.text.ARecognizeTaxiInvoiceHandle;
import com.heyu.api.alibaba.request.common.text.ARecognizeTaxiInvoiceRequest;
import com.heyu.api.baidu.handle.financial.BTaxiReceiptHandle;
import com.heyu.api.baidu.request.financial.BTaxiReceiptRequest;
import com.heyu.api.baidu.response.financial.BTaxiReceiptResp;
@ -11,137 +7,69 @@ import com.heyu.api.controller.BaseController;
import com.heyu.api.data.annotation.NotIntercept;
import com.heyu.api.data.utils.ApiR;
import com.heyu.api.data.utils.R;
import com.heyu.api.request.car.TaxiInvoiceRecognizeRequest;
import com.heyu.api.resp.car.RecognizeTaxiInvoiceResp;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.List;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
/**
* https://console.bce.baidu.com/support/#/api?product=AI&project=文字识别&parent=财务票据OCR&api=rest%2F2.0%2Focr%2Fv1%2Ftaxi_receipt&method=post
*
* 出租车发票识别百度OCR
*
* 支持识别全国各大城市的出租车票的全部字段包括发票号码发票代码电话日期金额
* 上下车时间里程等
*/
@Slf4j
@RestController
@RequestMapping("/taxi/invoice")
@NotIntercept
public class RecognizeTaxiInvoiceController extends BaseController {
@Autowired
private ARecognizeTaxiInvoiceHandle arRecognizeTaxiInvoiceHandle;
@Autowired
private BTaxiReceiptHandle bTaxiReceiptHandle;
@PostMapping("/recognize")
public R recognize(ARecognizeTaxiInvoiceRequest request) {
if (!hasImage(request)) {
return R.error("imageUrl和imageBase64不能同时为空");
public R recognize(@RequestBody TaxiInvoiceRecognizeRequest request) {
if (request == null) {
return R.error("请求参数不能为空");
}
if (isBlank(request.getImageBase64()) && isBlank(request.getImageUrl())) {
return R.error("imageBase64和imageUrl不能同时为空");
}
ApiR<RecognizeTaxiInvoiceResponse> aR = arRecognizeTaxiInvoiceHandle.handle(request);
if (isValidAliResponse(aR)) {
RecognizeTaxiInvoiceResp resp = toResp(aR.getData().getBody().getData());
if (CollectionUtils.isNotEmpty(resp.getRawItems())) {
return R.ok().setData(resp);
}
BTaxiReceiptRequest bRequest = toBaiduRequest(request);
ApiR<BTaxiReceiptResp> apiR = bTaxiReceiptHandle.handle(bRequest);
if (apiR == null || !apiR.isSuccess() || apiR.getData() == null) {
return R.error(thirdError(apiR));
}
ApiR<BTaxiReceiptResp> bR = bTaxiReceiptHandle.handle(toBaiduRequest(request));
if (bR != null && bR.isSuccess() && bR.getData() != null && bR.getData().getWordsResult() != null) {
return R.ok().setData(toResp(bR.getData().getWordsResult()));
BTaxiReceiptResp bResp = apiR.getData();
BTaxiReceiptResp.WordsResultDTO wordsResult = bResp.getWordsResult();
if (wordsResult == null) {
return R.error("未识别到出租车发票信息");
}
return R.error(!isBlank(thirdError(aR)) ? thirdError(aR) : thirdError(bR));
return R.ok().setData(toResp(wordsResult));
}
private boolean isValidAliResponse(ApiR<RecognizeTaxiInvoiceResponse> apiR) {
return apiR != null
&& apiR.isSuccess()
&& apiR.getData() != null
&& isSuccessStatusCode(apiR.getData().getStatusCode())
&& apiR.getData().getBody() != null
&& apiR.getData().getBody().getData() != null;
}
private BTaxiReceiptRequest toBaiduRequest(ARecognizeTaxiInvoiceRequest request) {
BTaxiReceiptRequest bTaxiReceiptRequest = new BTaxiReceiptRequest();
bTaxiReceiptRequest.setImageUrl(request.getImageUrl());
bTaxiReceiptRequest.setImageBase64(request.getImageBase64());
return bTaxiReceiptRequest;
}
private RecognizeTaxiInvoiceResp toResp(
RecognizeTaxiInvoiceResponseBody.RecognizeTaxiInvoiceResponseBodyData data) {
RecognizeTaxiInvoiceResp resp = new RecognizeTaxiInvoiceResp();
List<String> rawItems = new ArrayList<>();
if (data == null || CollectionUtils.isEmpty(data.getInvoices())) {
resp.setRawItems(rawItems);
return resp;
private BTaxiReceiptRequest toBaiduRequest(TaxiInvoiceRecognizeRequest request) {
BTaxiReceiptRequest bRequest = new BTaxiReceiptRequest();
if (isNotBlank(request.getImageBase64())) {
bRequest.setImageBase64(encodeParam(request.getImageBase64()));
}
RecognizeTaxiInvoiceResponseBody.RecognizeTaxiInvoiceResponseBodyDataInvoices invoice =
data.getInvoices().get(0);
if (invoice == null || CollectionUtils.isEmpty(invoice.getItems())) {
resp.setRawItems(rawItems);
return resp;
if (isNotBlank(request.getImageUrl())) {
bRequest.setImageUrl(encodeParam(request.getImageUrl()));
}
for (RecognizeTaxiInvoiceResponseBody.RecognizeTaxiInvoiceResponseBodyDataInvoicesItems item
: invoice.getItems()) {
if (item == null || isBlank(item.getText())) {
continue;
}
String text = item.getText().trim();
rawItems.add(text);
applyAliItem(resp, text);
}
resp.setRawItems(rawItems);
return resp;
}
private void applyAliItem(RecognizeTaxiInvoiceResp resp, String text) {
String value = parseValue(text);
if (text.contains("发票代码")) {
setInvoiceCode(resp, value);
return;
}
if (text.contains("发票号码") || text.contains("发票号")) {
setInvoiceNum(resp, value);
return;
}
if (text.contains("车号") || text.contains("车牌")) {
setTaxiNum(resp, value);
return;
}
if (text.contains("日期")) {
setDate(resp, value);
return;
}
if (text.contains("上车")) {
resp.setPickupTime(value);
return;
}
if (text.contains("下车")) {
resp.setDropoffTime(value);
return;
}
if (text.contains("时间")) {
resp.setTime(value);
return;
}
if (text.contains("金额") || text.contains("合计") || text.contains("票价")) {
setFare(resp, value);
}
}
private String parseValue(String text) {
int colonIndex = Math.max(text.lastIndexOf(':'), text.lastIndexOf(''));
if (colonIndex >= 0 && colonIndex + 1 < text.length()) {
return text.substring(colonIndex + 1).trim();
}
return text;
return bRequest;
}
private RecognizeTaxiInvoiceResp toResp(BTaxiReceiptResp.WordsResultDTO wordsResult) {
@ -165,36 +93,16 @@ public class RecognizeTaxiInvoiceController extends BaseController {
return resp;
}
private void setInvoiceCode(RecognizeTaxiInvoiceResp resp, String value) {
if (isBlank(resp.getInvoiceCode())) {
resp.setInvoiceCode(value);
private String encodeParam(String value) {
try {
return URLEncoder.encode(value, "UTF-8");
} catch (UnsupportedEncodingException e) {
log.error("URL编码失败:{}", value, e);
return value;
}
}
private void setInvoiceNum(RecognizeTaxiInvoiceResp resp, String value) {
if (isBlank(resp.getInvoiceNum())) {
resp.setInvoiceNum(value);
}
}
private void setTaxiNum(RecognizeTaxiInvoiceResp resp, String value) {
if (isBlank(resp.getTaxiNum())) {
resp.setTaxiNum(value);
}
}
private void setDate(RecognizeTaxiInvoiceResp resp, String value) {
if (isBlank(resp.getDate())) {
resp.setDate(value);
}
}
private void setFare(RecognizeTaxiInvoiceResp resp, String value) {
if (isBlank(resp.getFare())) {
resp.setFare(value);
}
if (isBlank(resp.getTotalFare())) {
resp.setTotalFare(value);
}
private boolean isNotBlank(String value) {
return value != null && value.trim().length() > 0;
}
}

View File

@ -1,27 +1,31 @@
package com.heyu.api.controller.car;
import com.aliyun.ocr20191230.models.RecognizeTrainTicketResponse;
import com.aliyun.ocr20191230.models.RecognizeTrainTicketResponseBody;
import com.heyu.api.alibaba.handle.common.text.ARecognizeTrainTicketHandle;
import com.heyu.api.alibaba.request.common.text.ARecognizeTrainTicketRequest;
import com.heyu.api.baidu.handle.financial.BTrainTicketHandle;
import com.heyu.api.baidu.request.financial.BTrainTicketRequest;
import com.heyu.api.baidu.response.financial.BTrainTicketResp;
import com.heyu.api.controller.BaseController;
import com.heyu.api.data.annotation.NotIntercept;
import com.heyu.api.data.utils.ApiR;
import com.heyu.api.data.utils.R;
import com.heyu.api.request.car.TrainTicketRecognizeRequest;
import com.heyu.api.resp.car.RecognizeTrainTicketResp;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/***
* https://next.api.aliyun.com/api/ocr/2019-12-30/RecognizeTrainTicket?tab=DOC&lang=JAVA
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
/**
* https://console.bce.baidu.com/support/#/api?product=AI&project=文字识别&parent=财务票据OCR&api=rest%2F2.0%2Focr%2Fv1%2Ftrain_ticket&method=post
*
* 火车票识别
*
* RecognizeTrainTicket
* 火车票识别百度OCR
*
* 支持识别各类火车票的全部字段包括车票号码乘车日期时间出发站到达站车次号席别座位号
* 乘车人姓名票价等信息
*/
@Slf4j
@RestController
@ -30,42 +34,90 @@ import org.springframework.web.bind.annotation.RestController;
public class RecognizeTrainTicketController extends BaseController {
@Autowired
private ARecognizeTrainTicketHandle aRecognizeTrainTicketHandle;
private BTrainTicketHandle bTrainTicketHandle;
@PostMapping("/recognize")
public R recognize(ARecognizeTrainTicketRequest request) {
if (!hasImage(request)) {
return R.error("imageUrl和imageBase64不能同时为空");
public R recognize(@RequestBody TrainTicketRecognizeRequest request) {
if (request == null) {
return R.error("请求参数不能为空");
}
if (isBlank(request.getImageBase64()) && isBlank(request.getImageUrl())) {
return R.error("imageBase64和imageUrl不能同时为空");
}
ApiR<RecognizeTrainTicketResponse> aR = aRecognizeTrainTicketHandle.handle(request);
if (!isValidAliResponse(aR)) {
return R.error(thirdError(aR));
BTrainTicketRequest bRequest = toBaiduRequest(request);
ApiR<BTrainTicketResp> apiR = bTrainTicketHandle.handle(bRequest);
if (apiR == null || !apiR.isSuccess() || apiR.getData() == null) {
return R.error(thirdError(apiR));
}
return R.ok().setData(toResp(aR.getData().getBody().getData()));
BTrainTicketResp bResp = apiR.getData();
BTrainTicketResp.WordsResultDTO wordsResult = bResp.getWordsResult();
if (wordsResult == null) {
return R.error("未识别到火车票信息");
}
return R.ok().setData(toResp(wordsResult));
}
private boolean isValidAliResponse(ApiR<RecognizeTrainTicketResponse> apiR) {
return apiR != null
&& apiR.isSuccess()
&& apiR.getData() != null
&& isSuccessStatusCode(apiR.getData().getStatusCode())
&& apiR.getData().getBody() != null
&& apiR.getData().getBody().getData() != null;
private BTrainTicketRequest toBaiduRequest(TrainTicketRecognizeRequest request) {
BTrainTicketRequest bRequest = new BTrainTicketRequest();
if (isNotBlank(request.getImageBase64())) {
bRequest.setImageBase64(encodeParam(request.getImageBase64()));
}
if (isNotBlank(request.getImageUrl())) {
bRequest.setImageUrl(encodeParam(request.getImageUrl()));
}
return bRequest;
}
private RecognizeTrainTicketResp toResp(
RecognizeTrainTicketResponseBody.RecognizeTrainTicketResponseBodyData data) {
private RecognizeTrainTicketResp toResp(BTrainTicketResp.WordsResultDTO words) {
RecognizeTrainTicketResp resp = new RecognizeTrainTicketResp();
resp.setPrice(data.getPrice());
resp.setDestination(data.getDestination());
resp.setDepartureStation(data.getDepartureStation());
resp.setDate(data.getDate());
resp.setNumber(data.getNumber());
resp.setSeat(data.getSeat());
resp.setName(data.getName());
resp.setLevel(data.getLevel());
resp.setName(words.getName());
resp.setNumber(words.getTrainNum());
resp.setDepartureStation(words.getStartingStation());
resp.setDestination(words.getDestinationStation());
resp.setLevel(words.getSeatCategory());
resp.setSeat(words.getSeatNum());
// 日期和时间合并百度返回独立date和time字段合并为"2017年08月05日 22:09开"格式
StringBuilder dateTime = new StringBuilder();
if (isNotBlank(words.getDate())) {
dateTime.append(words.getDate());
}
if (isNotBlank(words.getTime())) {
if (dateTime.length() > 0) {
dateTime.append(" ");
}
dateTime.append(words.getTime());
}
resp.setDate(dateTime.length() > 0 ? dateTime.toString() : null);
// 票价百度返回字符串转为Float
if (isNotBlank(words.getTicketRates())) {
try {
resp.setPrice(Float.parseFloat(words.getTicketRates()));
} catch (NumberFormatException e) {
log.warn("票价解析失败:{}", words.getTicketRates());
resp.setPrice(null);
}
}
return resp;
}
private String encodeParam(String value) {
try {
return URLEncoder.encode(value, "UTF-8");
} catch (UnsupportedEncodingException e) {
log.error("URL编码失败:{}", value, e);
return value;
}
}
private boolean isNotBlank(String value) {
return value != null && value.trim().length() > 0;
}
}

View File

@ -0,0 +1,29 @@
package com.heyu.api.request.car;
import lombok.Data;
/**
* 出租车发票识别请求参数百度OCR
*
* 支持识别全国各大城市的出租车票的全部字段包括发票号码发票代码电话日期金额
* 上下车时间里程等
*
* 百度文档https://console.bce.baidu.com/support/#/api?product=AI&project=文字识别&parent=财务票据OCR&api=rest%2F2.0%2Focr%2Fv1%2Ftaxi_receipt&method=post
*/
@Data
public class TaxiInvoiceRecognizeRequest {
/**
* 图像数据base64编码后进行urlencode要求base64编码和urlencode后大小不超过4M
* 支持jpg/jpeg/png/bmp格式
* 和url二选一
*/
private String imageBase64;
/**
* 图片完整URLURL长度不超过1024字节
* 和imageBase64二选一
*/
private String imageUrl;
}

View File

@ -0,0 +1,27 @@
package com.heyu.api.request.car;
import lombok.Data;
/**
* 火车票识别请求参数百度OCR
*
* 支持识别各类火车票的全部字段包括车票号码乘车日期时间出发站到达站车次号席别座位号
* 乘车人姓名票价等信息
*/
@Data
public class TrainTicketRecognizeRequest {
/**
* 图像数据base64编码后进行urlencode要求base64编码和urlencode后大小不超过4M
* 支持jpg/jpeg/png/bmp格式
* 和url二选一
*/
private String imageBase64;
/**
* 图片完整URLURL长度不超过1024字节
* 和imageBase64二选一
*/
private String imageUrl;
}

View File

@ -1,19 +1,13 @@
package com.heyu.api.resp.car;
import com.aliyun.tea.NameInMap;
import com.heyu.api.data.dto.BaseResp;
import lombok.Data;
/***
*
*
* https://next.api.aliyun.com/api/ocr/2019-12-30/RecognizeTrainTicket?useCommon=true
* 火车票识别
*
* RecognizeTrainTicket
*
/**
* 火车票识别响应
*
* 百度OCR文档https://console.bce.baidu.com/support/#/api?product=AI&project=文字识别&parent=财务票据OCR&api=rest%2F2.0%2Focr%2Fv1%2Ftrain_ticket&method=post
*/
@Data
public class RecognizeTrainTicketResp extends BaseResp {