提交修改
This commit is contained in:
parent
09348e7e53
commit
06a6e6c14a
@ -1,36 +1,395 @@
|
||||
package com.heyu.api.controller.card;
|
||||
|
||||
import com.heyu.api.baidu.handle.certificate.BBusinessLicenseHandle;
|
||||
import com.heyu.api.baidu.request.certificate.BBusinessLicenseRequest;
|
||||
import com.heyu.api.controller.BaseController;
|
||||
import com.heyu.api.controller.AbstractRecognizeController;
|
||||
import com.heyu.api.controller.BaiduOcrError;
|
||||
import com.heyu.api.data.annotation.CacheResult;
|
||||
import com.heyu.api.data.annotation.EbAuthentication;
|
||||
import com.heyu.api.data.annotation.NotIntercept;
|
||||
import com.heyu.api.data.utils.ApiR;
|
||||
import com.heyu.api.data.constants.ApiConstants;
|
||||
import com.heyu.api.data.utils.ImageInputUtils;
|
||||
import com.heyu.api.data.utils.ImageInputUtils.ResolvedImageInput;
|
||||
import com.heyu.api.data.utils.R;
|
||||
import com.heyu.api.data.utils.StringUtils;
|
||||
import com.heyu.api.request.card.BusinessLicenseRecognizeRequest;
|
||||
import com.heyu.api.resp.card.BusinessLicenseRecognizeResp;
|
||||
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;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 营业执照识别控制器
|
||||
* <p>
|
||||
* <b>接口背景</b>:用于商户入驻、企业资质核验、开票信息录入等场景,将营业执照照片自动识别为结构化字段,
|
||||
* 替代人工录入。底层对接百度智能云文字识别「营业执照识别」能力,由本服务完成参数校验、请求转发与字段映射。
|
||||
* </p>
|
||||
* <p>
|
||||
* 支持识别:单位名称、统一社会信用代码、法人、公司类型、组成形式、注册资本、实收资本、经营范围、
|
||||
* 成立日期、核准日期、有效期、登记机关、税务登记号、证件编号、公司地址等核心字段。
|
||||
* </p>
|
||||
*
|
||||
* <h3>百度官方文档</h3>
|
||||
* <ul>
|
||||
* <li>产品文档:<a href="https://cloud.baidu.com/doc/OCR/s/sk3h7y3zs">营业执照识别</a></li>
|
||||
* <li>接口地址:{@code POST https://aip.baidubce.com/rest/2.0/ocr/v1/business_license}</li>
|
||||
* </ul>
|
||||
*
|
||||
* <h3>本服务接口</h3>
|
||||
* <ul>
|
||||
* <li>路径:{@code POST /business/license/recognize}</li>
|
||||
* <li>Content-Type:{@code application/json}({@code @RequestBody})</li>
|
||||
* <li>鉴权:{@link EbAuthentication}(Tencent 鉴权头,见项目网关配置)</li>
|
||||
* <li>结果缓存:{@link CacheResult} 命中时不再调用平台,节省计费</li>
|
||||
* </ul>
|
||||
*
|
||||
* <h3>请求参数({@link BusinessLicenseRecognizeRequest})</h3>
|
||||
* <ul>
|
||||
* <li>imageUrlOrBase64:HTTP(S) 链接或 Base64 字符串,服务端自动识别(支持 jpg/jpeg/png/bmp)</li>
|
||||
* </ul>
|
||||
*
|
||||
* <h3>响应结构({@link BusinessLicenseRecognizeResp})</h3>
|
||||
* <ul>
|
||||
* <li>主体:companyName 单位名称 / registerNumber 统一社会信用代码 / companyLegalPerson 法人</li>
|
||||
* <li>资本:registerCapital 注册资本 / realCapital 实收资本</li>
|
||||
* <li>经营:business 经营范围 / companyType 公司类型 / compositionType 组成形式</li>
|
||||
* <li>日期:registerDate 成立日期 / approvalDate 核准日期 / validDateStart 有效期起 / validDateEnd 有效期止</li>
|
||||
* <li>其它:companyAddress 地址 / registerOrgan 登记机关 / taxRegisterCode 税务登记号 / certificateNumber 证件编号</li>
|
||||
* </ul>
|
||||
* <p>日期统一格式化为 {@code yyyyMMdd}(如 20250108);"长期"统一返回 {@code 29991231};百度未识别字段("无")统一返回 null。</p>
|
||||
*
|
||||
* <h3>返回约定(重要)</h3>
|
||||
* <ul>
|
||||
* <li>一律 {@code R.ok()};入参校验失败、平台异常、识别结果为空等情况,将说明写入 {@code msg},
|
||||
* {@code data} 可能为空或字段不全(对外不暴露「百度」字样,日志内可排查)</li>
|
||||
* <li>入参校验失败时<strong>未调用百度、不计费</strong></li>
|
||||
* </ul>
|
||||
*
|
||||
* @author heyu
|
||||
* @since 1.0.0
|
||||
* @see BusinessLicenseRecognizeRequest
|
||||
* @see BusinessLicenseRecognizeResp
|
||||
*/
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequestMapping("/business/license")
|
||||
@NotIntercept
|
||||
public class BusinessLicenseRecognizeController extends BaseController {
|
||||
public class BusinessLicenseRecognizeController extends AbstractRecognizeController {
|
||||
|
||||
@Autowired
|
||||
private BBusinessLicenseHandle bBusinessLicenseHandle;
|
||||
/** 百度营业执照识别 API 路径 */
|
||||
private static final String BUSINESS_LICENSE_URI = "/rest/2.0/ocr/v1/business_license";
|
||||
|
||||
@RequestMapping("/recognize")
|
||||
/** 营业执照识别无 side 概念,统一占位以复用父类上下文 */
|
||||
private static final String SIDE_PLACEHOLDER = "business_license";
|
||||
|
||||
/** 百度对未识别字段返回的占位值,需在映射时清洗为 null */
|
||||
private static final String BAIDU_EMPTY = "无";
|
||||
|
||||
/** "长期"有效期的统一表达 */
|
||||
private static final String LONG_TERM_DATE = "29991231";
|
||||
|
||||
/**
|
||||
* 营业执照识别
|
||||
*
|
||||
* @param request 营业执照识别请求
|
||||
* @return {@link BusinessLicenseRecognizeResp}
|
||||
*/
|
||||
@EbAuthentication(tencent = ApiConstants.TENCENT_AUTH)
|
||||
@CacheResult
|
||||
public R recognize(BusinessLicenseRecognizeRequest request) {
|
||||
BBusinessLicenseRequest businessLicenseRequest = new BBusinessLicenseRequest();
|
||||
businessLicenseRequest.setImageUrl(request.getImageUrl());
|
||||
businessLicenseRequest.setImageBase64(request.getImageBase64());
|
||||
ApiR<Map> bR = bBusinessLicenseHandle.handle(businessLicenseRequest);
|
||||
return com.heyu.api.controller.ocr.BaiduOcrResult.raw(bR);
|
||||
@PostMapping("/recognize")
|
||||
public R recognize(@RequestBody BusinessLicenseRecognizeRequest request) {
|
||||
long start = System.currentTimeMillis();
|
||||
RecognizeContext ctx = null;
|
||||
try {
|
||||
// ---------- 步骤①:参数校验(不调百度、不扣费) ----------
|
||||
String validateError = validateRequest(request);
|
||||
if (validateError != null) {
|
||||
ResolvedImageInput validateImage = request != null
|
||||
? ImageInputUtils.resolve(request.getImageUrlOrBase64()) : null;
|
||||
log.info("营业执照识别:参数检查没通过,接口仍返回成功并附带提示(还没调识别、不扣费)。{} 返回给客户:{}",
|
||||
buildInputLogContext(request, validateImage),
|
||||
abbreviate(validateError, 120));
|
||||
return okResult(SIDE_PLACEHOLDER, validateError, null);
|
||||
}
|
||||
|
||||
// ---------- 步骤②:解析影像入参 & 构建上下文 ----------
|
||||
ResolvedImageInput imageInput = ImageInputUtils.resolve(request.getImageUrlOrBase64());
|
||||
ctx = new RecognizeContext(
|
||||
SIDE_PLACEHOLDER,
|
||||
imageInput,
|
||||
buildInputLogContext(request, imageInput));
|
||||
|
||||
// ---------- 步骤③:组装百度 API 请求体 ----------
|
||||
String content = buildRequestContent(imageInput);
|
||||
if (isBlank(content)) {
|
||||
log.error("营业执照识别:组装请求失败,请求里没带有效图片。{}。{}",
|
||||
ctx.imageInput.getType().getDesc(), ctx.inputLog);
|
||||
return okResult(SIDE_PLACEHOLDER, formatHint(
|
||||
"报文组装异常",
|
||||
"识别请求体在序列化后未包含任何影像载荷,平台侧无法受理本次识别",
|
||||
"请核对 imageUrlOrBase64 是否非空且为有效 Base64 或 HTTP(S) 链接",
|
||||
"影像模式=" + ctx.imageInput.getType().name()
|
||||
), null);
|
||||
}
|
||||
|
||||
// ---------- 步骤④:调用百度平台识别 ----------
|
||||
Map<String, Object> platformResult = callPlatform(content, ctx);
|
||||
if (platformResult == null) {
|
||||
return okResult(SIDE_PLACEHOLDER, formatHint(
|
||||
"服务无回执",
|
||||
"识别指令已下发,但在约定时间内未收到平台可解析的 JSON 回执",
|
||||
"建议间隔 3~5 秒重试;若连续失败,请记录 traceId、调用时刻并联系技术支持排查链路",
|
||||
"影像模式=" + ctx.imageInput.getType().name()
|
||||
), null);
|
||||
}
|
||||
|
||||
// ---------- 步骤⑤:解析平台结果 → 构建营业执照响应 ----------
|
||||
BusinessLicenseRecognizeResp data = buildResp(platformResult);
|
||||
String hint = resolvePlatformHint(platformResult, ctx, data);
|
||||
|
||||
// ---------- 步骤⑥:日志记录 & 返回 ----------
|
||||
logRecognizeResult(ctx, platformResult, data, hint, start);
|
||||
return okResult(SIDE_PLACEHOLDER, hint, data);
|
||||
|
||||
} catch (Exception e) {
|
||||
long cost = System.currentTimeMillis() - start;
|
||||
ResolvedImageInput fallbackImage = request != null
|
||||
? ImageInputUtils.resolve(request.getImageUrlOrBase64()) : null;
|
||||
String mode = ctx != null ? ctx.imageInput.getType().getDesc()
|
||||
: (fallbackImage != null ? fallbackImage.getType().getDesc() : "未知");
|
||||
log.error("营业执照识别:程序运行出错,耗时 {} ms。{}。客户传的:{}。异常:{} - {}",
|
||||
cost, mode, buildInputLogContext(request, fallbackImage),
|
||||
e.getClass().getSimpleName(),
|
||||
e.getMessage() != null ? e.getMessage() : "无具体说明", e);
|
||||
return okResult(SIDE_PLACEHOLDER, formatHint(
|
||||
"运行时故障",
|
||||
"服务端在处理识别流程时抛出未预期异常,识别结果不可用",
|
||||
"请勿重复高频重试;请保存 traceId、异常发生时间,由技术支持结合堆栈进一步定位",
|
||||
"异常类型=" + e.getClass().getSimpleName()
|
||||
+ (e.getMessage() != null ? ",摘要=" + e.getMessage() : "")
|
||||
), null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 子类钩子:营业执照识别只有一种响应类型,无 side 区分。
|
||||
*/
|
||||
@Override
|
||||
protected Object defaultEmptyResp(String side) {
|
||||
return new BusinessLicenseRecognizeResp();
|
||||
}
|
||||
|
||||
// ===================== 流程拆分方法 =====================
|
||||
|
||||
private Map<String, Object> callPlatform(String content, RecognizeContext ctx) {
|
||||
int len = content.length();
|
||||
log.info("营业执照识别:开始调用平台识别。{},请求大小约 {} 字节。{}",
|
||||
ctx.imageInput.getType().getDesc(), len, ctx.inputLog);
|
||||
Map<String, Object> result = requestBaidu(BUSINESS_LICENSE_URI, content);
|
||||
if (result == null) {
|
||||
log.error("营业执照识别:平台没有返回结果(可能网络超时、鉴权失败或响应无法解析)。{},请求约 {} 字节。{}",
|
||||
ctx.imageInput.getType().getDesc(), len, ctx.inputLog);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析平台返回结果,判断是否需要向客户返回提示信息。
|
||||
* <p>判断顺序:</p>
|
||||
* <ol>
|
||||
* <li>error_code 存在 → 平台业务拒绝</li>
|
||||
* <li>words_result 缺失或为空 → 平台未识别出营业执照</li>
|
||||
* <li>响应对象全部 String 字段为空 → 字段映射失败</li>
|
||||
* <li>以上均不命中 → 返回 null(识别正常)</li>
|
||||
* </ol>
|
||||
*/
|
||||
private String resolvePlatformHint(Map<String, Object> platformResult, RecognizeContext ctx,
|
||||
BusinessLicenseRecognizeResp data) {
|
||||
Object errorCodeObj = platformResult.get("error_code");
|
||||
if (errorCodeObj != null) {
|
||||
String errorCode = String.valueOf(errorCodeObj);
|
||||
Object errorMsgObj = platformResult.get("error_msg");
|
||||
String errorMsg = errorMsgObj != null ? errorMsgObj.toString() : "平台未返回文字描述";
|
||||
String category = BaiduOcrError.categoryOf(errorCode);
|
||||
log.error("营业执照识别:平台拒绝了本次识别。[{}] 错误码 {},原因:{}。{}。客户传的:{}。{}",
|
||||
category, errorCode, errorMsg,
|
||||
ctx.imageInput.getType().getDesc(),
|
||||
ctx.inputLog, buildPlatformReceiptSummary(platformResult));
|
||||
return formatHint(
|
||||
category,
|
||||
BaiduOcrError.reasonOf(errorCode),
|
||||
BaiduOcrError.suggestionOf(errorCode, "营业执照"),
|
||||
"错误码=" + errorCode + ",错误描述=" + errorMsg
|
||||
);
|
||||
}
|
||||
if (isWordsResultEmpty(platformResult)) {
|
||||
log.info("营业执照识别:平台返回了,但 words_result 为空(可能不是营业执照、画面残缺或非证件照)。{}。客户传的:{}。{}",
|
||||
ctx.imageInput.getType().getDesc(),
|
||||
ctx.inputLog, buildPlatformReceiptSummary(platformResult));
|
||||
return formatHint(
|
||||
"结构化结果缺失",
|
||||
"平台回执未包含可解析的营业执照识别结果,无法进入字段映射环节",
|
||||
"优先排查:① 画面是否为完整营业执照(含单位名称/信用代码等核心信息);② 是否模糊 / 反光 / 严重倾斜;"
|
||||
+ "③ 使用 URL 时确保平台抓取节点可访问且无 403/302 拦截",
|
||||
"解析状态=结果对象为空"
|
||||
);
|
||||
}
|
||||
if (isAllStringFieldsBlank(data)) {
|
||||
log.info("营业执照识别:平台有返回,但单位名称/信用代码/法人等字段一个都没识别出来。{}。客户传的:{}。平台回执:{}",
|
||||
ctx.imageInput.getType().getDesc(),
|
||||
ctx.inputLog, buildPlatformReceiptSummary(platformResult));
|
||||
return formatHint(
|
||||
"字段映射为空",
|
||||
"平台回执已通过结构校验,但单位名称、统一社会信用代码、法人等结构化字段均未命中",
|
||||
"请确认上传图片为正面完整的营业执照(含国徽与正文);推荐:平铺拍摄、避开反光、保证四角与文字清晰",
|
||||
"已映射字段数=0"
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void logRecognizeResult(RecognizeContext ctx, Map<String, Object> platformResult,
|
||||
Object data, String hint, long start) {
|
||||
long cost = System.currentTimeMillis() - start;
|
||||
int mapped = countNonBlankStringFields(data);
|
||||
if (StringUtils.isNotBlank(hint)) {
|
||||
log.info("营业执照识别:处理结束(接口仍返回成功,但带了提示信息)。耗时 {} ms,识别出 {} 个字段。{}。客户传的:{}。平台回执:{}。给客户的提示:{}",
|
||||
cost, mapped, ctx.imageInput.getType().getDesc(),
|
||||
ctx.inputLog, buildPlatformReceiptSummary(platformResult), abbreviate(hint, 120));
|
||||
} else {
|
||||
log.info("营业执照识别:识别成功。耗时 {} ms,共识别出 {} 个字段。{}。客户传的:{}。平台回执:{}",
|
||||
cost, mapped, ctx.imageInput.getType().getDesc(),
|
||||
ctx.inputLog, buildPlatformReceiptSummary(platformResult));
|
||||
}
|
||||
}
|
||||
|
||||
// ===================== 校验 =====================
|
||||
|
||||
private String validateRequest(BusinessLicenseRecognizeRequest request) {
|
||||
if (request == null) {
|
||||
log.info("营业执照识别:没收到任何请求参数(表单未绑定成功),直接拒绝,未调用识别、不扣费");
|
||||
return formatHint(
|
||||
"入参绑定失败",
|
||||
"控制器未接收到可绑定的请求对象,所有业务字段均为空",
|
||||
"请确认使用 POST 提交;Content-Type 为 application/json;字段名为 imageUrlOrBase64",
|
||||
"绑定结果=BusinessLicenseRecognizeRequest 为 null"
|
||||
);
|
||||
}
|
||||
ImageInputUtils.ValidationResult imageValidation =
|
||||
ImageInputUtils.validate(request.getImageUrlOrBase64());
|
||||
if (!imageValidation.isValid()) {
|
||||
log.info("营业执照识别:imageUrlOrBase64 校验未通过({}),未调用识别、不扣费。原因:{}。{}",
|
||||
imageValidation.getCategory(),
|
||||
imageValidation.getReason(),
|
||||
buildInputLogContext(request, null));
|
||||
return formatHint(
|
||||
imageValidation.getCategory(),
|
||||
imageValidation.getReason(),
|
||||
imageValidation.getSuggestion(),
|
||||
imageValidation.getDetail()
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// ===================== 请求 / 响应构造 =====================
|
||||
|
||||
private String buildRequestContent(ResolvedImageInput imageInput) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if (imageInput == null || StringUtils.isBlank(imageInput.getFormValue())) {
|
||||
return sb.toString();
|
||||
}
|
||||
if (ImageInputUtils.ImageInputType.URL == imageInput.getType()) {
|
||||
sb.append("&url=").append(imageInput.getFormValue());
|
||||
} else {
|
||||
sb.append("&image=").append(imageInput.getFormValue());
|
||||
}
|
||||
// 默认不开启高精度版与风险检测,保持基础计费
|
||||
sb.append("&accuracy=normal");
|
||||
sb.append("&risk_warn=false");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 将百度返回的 words_result 映射为对外响应对象。
|
||||
* <p>映射规则:</p>
|
||||
* <ul>
|
||||
* <li>百度返回的占位值"无" → null(保持响应整洁)</li>
|
||||
* <li>日期字段统一格式化为 yyyyMMdd;"长期" → 29991231</li>
|
||||
* </ul>
|
||||
*/
|
||||
private BusinessLicenseRecognizeResp buildResp(Map<String, Object> data) {
|
||||
BusinessLicenseRecognizeResp resp = new BusinessLicenseRecognizeResp();
|
||||
resp.setCompanyName(clean(data, "单位名称"));
|
||||
resp.setRegisterNumber(clean(data, "社会信用代码"));
|
||||
resp.setCompanyLegalPerson(clean(data, "法人"));
|
||||
resp.setCompanyType(clean(data, "类型"));
|
||||
resp.setCompositionType(clean(data, "组成形式"));
|
||||
resp.setRegisterCapital(clean(data, "注册资本"));
|
||||
resp.setRealCapital(clean(data, "实收资本"));
|
||||
resp.setBusiness(clean(data, "经营范围"));
|
||||
resp.setCompanyAddress(clean(data, "地址"));
|
||||
resp.setRegisterOrgan(clean(data, "登记机关"));
|
||||
resp.setTaxRegisterCode(clean(data, "税务登记号"));
|
||||
resp.setCertificateNumber(clean(data, "证件编号"));
|
||||
resp.setRegisterDate(normalizeDate(clean(data, "成立日期")));
|
||||
resp.setApprovalDate(normalizeDate(clean(data, "核准日期")));
|
||||
resp.setValidDateStart(normalizeDate(clean(data, "有效期起始日期")));
|
||||
resp.setValidDateEnd(normalizeDate(clean(data, "有效期")));
|
||||
return resp;
|
||||
}
|
||||
|
||||
/**
|
||||
* 从 words_result 取字段并清洗百度占位值"无"。
|
||||
*/
|
||||
private String clean(Map<String, Object> data, String field) {
|
||||
String value = getWords(data, field);
|
||||
if (StringUtils.isBlank(value) || BAIDU_EMPTY.equals(value.trim())) {
|
||||
return null;
|
||||
}
|
||||
return value.trim();
|
||||
}
|
||||
|
||||
/**
|
||||
* 将"2025年01月08日""2025-01-08"等格式统一为 yyyyMMdd;含"长期"返回 29991231;无法解析则原样返回。
|
||||
*/
|
||||
private String normalizeDate(String raw) {
|
||||
if (StringUtils.isBlank(raw)) {
|
||||
return null;
|
||||
}
|
||||
if (raw.contains("长期")) {
|
||||
return LONG_TERM_DATE;
|
||||
}
|
||||
String digits = raw.replaceAll("[^0-9]", "");
|
||||
if (digits.length() == 8) {
|
||||
return digits;
|
||||
}
|
||||
return raw;
|
||||
}
|
||||
|
||||
// ===================== 私有工具 =====================
|
||||
|
||||
private String formatHint(String category, String reason, String suggestion, String detail) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("【营业执照识别·").append(category).append("】").append(reason);
|
||||
if (StringUtils.isNotBlank(detail)) {
|
||||
sb.append("|定位信息:").append(detail);
|
||||
}
|
||||
sb.append("|处置指引:").append(suggestion);
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/** 入参日志说明(不打印影像正文,只说类型与长度) */
|
||||
private String buildInputLogContext(BusinessLicenseRecognizeRequest request, ResolvedImageInput imageInput) {
|
||||
if (request == null) {
|
||||
return "未收到请求体";
|
||||
}
|
||||
String modeDesc = imageInput != null ? imageInput.getType().getDesc() : "影像未解析";
|
||||
int rawLen = imageInput != null
|
||||
? textLength(imageInput.getRawValue())
|
||||
: textLength(request.getImageUrlOrBase64());
|
||||
return String.format("%s,影像原始长度 %d 字符", modeDesc, rawLen);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,25 +1,26 @@
|
||||
package com.heyu.api.request.card;
|
||||
|
||||
|
||||
import com.heyu.api.data.dto.BaseReq;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 营业执照识别请求参数。
|
||||
*
|
||||
* 对外提供简洁接口,支持识别营业执照的单位名称、统一社会信用代码、法人、注册资本、经营范围、
|
||||
* 成立/核准日期、有效期、登记机关等字段。
|
||||
*/
|
||||
@Data
|
||||
public class BusinessLicenseRecognizeRequest extends BaseReq {
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 营业执照图片的url
|
||||
* 影像入参(URL 或 Base64 二合一):
|
||||
* <ul>
|
||||
* <li>HTTP/HTTPS 图片链接(≤1024 字符,未 urlencode 时由服务端自动编码)</li>
|
||||
* <li>图片 Base64 字符串(支持 jpg/jpeg/png/bmp;可带 data:image/...;base64, 前缀;
|
||||
* 编码后 urlencode 前建议≤4M,未 urlencode 时由服务端自动编码)</li>
|
||||
* </ul>
|
||||
* 服务端根据内容自动识别为链接或 Base64。
|
||||
*/
|
||||
private String imageUrl;
|
||||
|
||||
/**
|
||||
* 营业执照base 64 编码
|
||||
*/
|
||||
private String imageBase64;
|
||||
|
||||
|
||||
|
||||
private String imageUrlOrBase64;
|
||||
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user