diff --git a/api.md b/api.md index 4bdfc40..dcc4c74 100644 --- a/api.md +++ b/api.md @@ -1,266 +1,59 @@ -# API 文档(领取与兑奖流程) +# 接口文档(活动 + OCR 领取) + +## 总览 +- 接口均返回 `ResultObject`:`{ code, msg, data }` +- 所有接口已开放匿名访问 + +## 当前活动 +- 方法:GET +- 路径:`/marriage/activity/current` +- 入参:无 +- 出参: + - `data`:`{ activityName, activityStartTime, activityEndTime, money, status }` +- 说明:仅当当前时间处于活动开始与结束时间范围、且活动启用(`status=0`)时返回数据;否则 `data=null` + +## 上传结婚证图片(OCR) +- 方法:POST +- 路径:`/marriage/ocr/upload` +- 入参:`multipart/form-data` + - `file`:结婚证图片文件 +- 出参: + - `data`:`{ uploadId }` +- 说明:图片内容以 Base64 暂存至 Redis(键:`OCR_UPLOAD-{uploadId}`,TTL 10 分钟) + +## 发送短信验证码 +- 方法:POST +- 路径:`/marriage/common/sms` +- 入参:`CommSmsDTO` + - `mobile`:手机号(必填) + - `type`:验证码类型(`0` 登录;`1` 兑换领取;`2` OCR;本流程使用 `3`) +- 出参:`code=200` +- 说明:验证码缓存键 `VERICODE_MOBILE-{type}-{mobile}`,TTL 10 分钟 + +## 校验短信验证码 +- 方法:POST +- 路径:`/marriage/common/checkCode` +- 入参:JSON + - `mobile`:手机号(必填) + - `type`:验证码类型(本流程使用 `3`) + - `smsCode`:短信验证码(必填) +- 出参:`code=200`(校验通过) +- 若已参与正在进行的活动,MarriageCodeVO + +## 领取前校验(OCR流程) +- 方法:POST +- 路径:`/marriage/receiveCheck2` +- 入参:`MarriageCodeDTO` + - `marriageNo`:结婚证字号(必填,长度≥11,且需符合活动条件) + - `receiveName`:领取人姓名(必填) + - `receiveMobile`:领取人手机号(必填) + - `code`:核验码(必填) + - `smsCode`:短信验证码(必填,校验键 `VERICODE_MOBILE-3-{mobile}`) + - `salesNo`:站点号(选填) + - `signImage`:领取人电子签名(选填,预校验阶段可为空) +- 出参:`ResultObject`(用于前端预览/继续领取) +- 说明:校验重复领取、证号格式与活动条件;短信验证码校验通过后返回校验结果视图 本文件整理新婚送福活动前端页面所用接口,包括领取流程与兑奖页面改造所需的现有接口与拟新增接口。文档基于当前代码库(com-marriage-client 与 com-admin-client)。 -## 基本信息 -- 服务与端口: - - 领取端(com-marriage-client):`http://localhost:8200`,应用名 `nxfc-marriage-client` - - 后台端(com-admin-client):`http://localhost:8000`,应用名 `nxfc-admin-client` -- 认证: - - 站点登录与短信验证接口位于 `com-marriage-client` 的 `/marriage/common` 路径下。 - - 后台活动管理接口位于 `com-admin-client` 的 `/admin/activity` 路径下(通常用于管理端)。 - ---- - -## 领取流程页面 - -### 1)活动介绍页 -用于展示当前活动的名称、时间和面额信息。 - -- 拟新增(面向领取端,便于前端直接获取展示数据) - - 方法:`GET` - - 路径:`/marriage/activity/current` - - 入参:无 - - 出参(示例): - ```json - { - "code": 200, - "msg": "", - "data": { - "activityName": "新婚送福", - "activityStartTime": "2025-09-15 00:00:00", - "activityEndTime": "2025-10-31 23:59:59", - "money": 6000, - "status": 1 - } - } - ``` - - 备注:如暂未在领取端提供该接口,可临时通过后台端获取列表接口获得活动信息: - - 方法:`POST` - - 路径:`/admin/activity/list` - - 入参:无 - - 出参:`ResultObject` 包含活动集合,字段参考 `MarriageActivity`。 - -### 2)OCR识别结婚证,自动带出信息,领取二维码页 -为避免用户手动输入,新增 OCR 流程:上传结婚证图片并识别证件信息,前端使用识别结果自动填充表单,再进行短信校验与领取。 - -- OCR 上传图片 [新增] - - 方法:`POST` - - 路径:`/marriage/ocr/upload` - - 入参:`multipart/form-data`,字段:`file`(结婚证图片) - - 出参(示例): - ```json - { "code": 200, "msg": "", "data": { "uploadId": "ab12cd34..." } } - ``` - - 备注:服务端将图片内容以 Base64 缓存于 Redis(键:`OCR_UPLOAD-{uploadId}`,有效期 10 分钟),不落盘文件。 - -- 发送短信验证码 - - 方法:`POST` - - 路径:`/marriage/common/sms` - - 入参:`CommSmsDTO` - - `mobile`:手机号(必填) - - `type`:验证码类型,`0`=登录;`1`=兑换领取;`2`=OCR识别(本页使用 `2`) [扩展] - - 出参(示例): - ```json - { "code": 200, "msg": "", "data": null } - ``` - - 备注:当前实现对 `type=1` 的校验逻辑使用了 `code` 字段比对,可能与期望不一致(代码中以 `MarriageCode::getCode == mobile` 判断重复)。如需严格校验手机号唯一性,可调整实现。 - -- OCR 识别并返回证件信息(供前端自动填充) [新增] - - 方法:`POST` - - 路径:`/marriage/ocr/parse` - - 入参:`OcrParseDTO` - - `mobile`:手机号(必填) - - `smsCode`:短信验证码(必填,取自上方 `/sms`,`type=2`) - - `uploadId`:上传接口返回的标识(必填) - - 出参(示例): - ```json - { - "code": 200, - "msg": "", - "data": { - "raw": "<百度OCR原始JSON字符串>", - "words": ["宁夏回族自治区婚姻登记证", "字号6403812025001056", "男方张三", "女方李四", "登记日期2025-10-01"], - "parsed": { - "marriageNo": "6403812025001056", - "husbandName": "张三", - "wifeName": "李四", - "registerDate": "2025-10-01" - } - } - } - ``` - - 备注:前端可将 `parsed.marriageNo` 用于后续校验与领取,将 `husbandName`/`wifeName`用于展示或校验提示;若识别失败,提示重新上传清晰图片。 - -- 领取前校验(生成二维码前的校验与预览) - - 方法:`POST` - - 路径:`/marriage/receiveCheck` - - 入参:`MarriageCodeDTO` - - `marriageNo`:结婚登记证号(必填,长度≥11,且需符合活动条件) - - `receiveName`:领取人姓名(必填) - - `receiveMobile`:领取人手机号(必填) - - `code`:核销码(必填) - - `smsCode`:短信验证码(必填,取自上方 `/sms`,`type=2`) - - `signImage`:领取人电子签名(选填,校验阶段可为空) - - `salesNo`:站点号(选填,用于落库统计) - - 出参:`ResultObject`,其中包含可用于二维码展示的 `code` 等字段。 - - 业务规则摘要: - - 校验结婚证号格式与活动条件。 - - 校验手机号、结婚证号、核销码是否已参与或使用过。 - - 校验短信验证码正确性(Redis 缓存键:`VERICODE_MOBILE 1-`)。 - -- 确认领取(落库并置为已核销) - - 方法:`POST` - - 路径:`/marriage/receiveCode` - - 入参:`MarriageCodeDTO` - - 与 `receiveCheck` 基本一致,但 `signImage` 必填(签字图片,建议前端以 Base64 上传) - - 出参:`ResultObject`(成功返回 200) - - 落库行为:将 `MarriageCode` 的 `marriageNo`、`receiveName`、`receiveMobile`、`signImage`、`salesNo`、`receiveMoney=6000`、`receiveTime`、`status=1` 写入并更新。 - -### 3)查看已领取二维码页(包括二维码状态) -支持按站点和月份查看领取列表统计;也建议提供按核销码查询单条状态的接口。 - -- 已有:按站点号与月份分页统计列表 - - 方法:`POST` - - 路径:`/marriage/codeList` - - 入参:`MarriageCodeDTO` - - `salesNo`:站点号(必填) - - `page`、`size`:分页参数(必填) - - `dataTime`:月份(格式 `yyyy-MM`,可选,默认当前月) - - 出参:`ResultObject` - - `codeList`:列表(`MarriageCodeListVO`) - - `receiveCount`:数量合计(字符串) - - `receiveAmount`:金额合计(字符串,单位分) - -- 拟新增:按核销码查询状态(用于二维码状态页) - - 方法:`POST` - - 路径:`/marriage/code/status` - - 入参: - ```json - { "code": "xxxxxx" } - ``` - - 出参(示例): - ```json - { - "code": 200, - "msg": "", - "data": { - "code": "xxxxxx", - "status": 0, - "marriageNo": null, - "receiveName": null, - "receiveMobile": null, - "receiveTime": null - } - } - ``` -- 备注:`status=0` 未核销;`status=1` 已核销。已核销时返回对应的领取人信息与时间。 - ---- - -## OCR识别流程(免手动输入) - -### 端到端流程 -1. 前端上传结婚证图片:`POST /marriage/ocr/upload` [新增] → 返回 `uploadId` -2. 发送短信验证码:`POST /marriage/common/sms`(`type=2`) [扩展] -3. 识别证件信息:`POST /marriage/ocr/parse`(`mobile`、`smsCode`、`uploadId`) [新增] → 返回 `parsed.marriageNo` 等信息 -4. 自动填充领取表单,走校验与领取:`POST /marriage/receiveCheck` → `POST /marriage/receiveCode` - -### 安全与权限 -- `POST /marriage/ocr/**` 与 `POST /marriage/common/sms` 已放行匿名访问,用于领取端无登录场景。 -- 后端不存储用户上传的原始图片文件,仅在 Redis 缓存 Base64(10 分钟),减少存储与泄露风险。 - -### 配置项标注 -- 百度 OCR 相关配置(开发环境) [新增] - - `baidu.ocr.appId`、`baidu.ocr.apiKey`、`baidu.ocr.secretKey`(建议通过环境变量注入) - - `baidu.ocr.authUrl`(默认:`https://aip.baidubce.com/oauth/2.0/token`) - - `baidu.ocr.generalUrl`(默认:`https://aip.baidubce.com/rest/2.0/ocr/v1/general_basic`) - - `baidu.ocr.storagePath`(当前不落盘,仅占位) - -### 测试说明 -- 集成测试覆盖 OCR 上传与识别接口,使用本地伪服务模拟百度返回 [新增] - - 测试类:`com-marriage-client/src/test/java/com/jinrui/marriage/client/controller/OcrControllerTest.java` - - 通过属性重定向百度 URL 到本地:`baidu.ocr.authUrl`、`baidu.ocr.generalUrl` - - 断言返回的 `parsed.marriageNo` 包含示例字号片段 - ---- - -## 兑奖页面(改为自动带出结婚证号、手机号、姓名) - -目标:在兑奖页输入(或扫码)核销码后,自动拉取该码对应的 `marriageNo`、`receiveMobile`、`receiveName` 等信息进行表单预填。 - -- 拟新增:根据核销码获取领取信息(用于自动带出) - - 方法:`POST` - - 路径:`/marriage/code/info` - - 入参: - ```json - { "code": "xxxxxx" } - ``` - - 出参(示例): - ```json - { - "code": 200, - "msg": "", - "data": { - "code": "xxxxxx", - "status": 1, - "marriageNo": "NX-2025-XXXXXXXXX", - "receiveName": "张三", - "receiveMobile": "13800000000", - "receiveTime": "2025-10-10 12:00:00", - "salesNo": "1001" - } - } - ``` - - 备注: - - 若未领取(`status=0`),则上述字段为空或不返回;前端可引导先走“领取流程”。 - - 若已领取(`status=1`),则用于自动填充兑奖页的表单,减少重复输入。 - ---- - -## 站点登录(如需) -用于站点管理后台或业务员端登录。 - -- 发送登录短信验证码(type=0) - - 方法:`POST` - - 路径:`/marriage/common/sms` - - 入参:`CommSmsDTO`(`mobile`,`type=0`) - - 出参:`ResultObject` - -- 登录 - - 方法:`POST` - - 路径:`/marriage/common/login` - - 入参:`MarrigeLoginDTO` - - `mobile`、`password`(当前固定为 `88888888`)、`smsCode` - - 出参:`ResultObject`(包含登录票据与站点信息) - ---- - -## 返回结构与错误码 -- 所有接口统一返回 `ResultObject`: - - `code`:业务状态码,`200` 表示成功 - - `msg`:提示信息 - - `data`:实际数据载体(对象或集合) -- 常见失败信息(摘录): - - `结婚证字号不能为空/长度不对/不符合活动条件` - - `领取人姓名不能为空/领取人手机号不能为空` - - `核验码不能为空/此代金卷不正确/此代金卷已使用过` - - `该领取人已领取过新婚送福活动刮刮乐/这个证号已参与过活动` - - `验证码错误,请重新输入` - ---- - -## 字段模型参考 -- `MarriageCodeDTO` - - `marriageNo`、`receiveName`、`code`、`receiveMobile`、`signImage`、`salesNo`、`smsCode`、`dataTime` -- `CommSmsDTO` - - `mobile`、`type`(`0` 登录,`1` 兑换领取) -- `MarriageCodeVO` / `MarriageCodeListVO` - - 列表与详情视图,包含领取统计与单条领取信息 - ---- - -## 前端配合建议 -- 二维码内容直接使用核销码 `code` 编码,状态页通过 `code/status` 查询。 -- 兑奖页在扫描或输入核销码后,先调用 `code/info` 自动填充,再根据业务需要提交后续操作。 -- 如本地开发环境不具备外网资源(DB/Redis/微信),建议提供 `local` profile,临时屏蔽定时任务与外部依赖,仅用于接口联调与页面开发。 +# \ No newline at end of file diff --git a/com-core-model/src/main/java/com/jinrui/core/model/dto/CheckCodeDto.java b/com-core-model/src/main/java/com/jinrui/core/model/dto/CheckCodeDto.java new file mode 100644 index 0000000..d9fd341 --- /dev/null +++ b/com-core-model/src/main/java/com/jinrui/core/model/dto/CheckCodeDto.java @@ -0,0 +1,17 @@ +package com.jinrui.core.model.dto; + +import lombok.*; +import lombok.experimental.Accessors; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +@EqualsAndHashCode(callSuper = false) +@Accessors(chain = true) +public class CheckCodeDto { + private String mobile; + private String verifyCode; + private String smsCode; + private String type; +} diff --git a/com-marriage-client/src/main/java/com/jinrui/marriage/client/config/SecurityConfig.java b/com-marriage-client/src/main/java/com/jinrui/marriage/client/config/SecurityConfig.java index e811d07..29f3a8d 100755 --- a/com-marriage-client/src/main/java/com/jinrui/marriage/client/config/SecurityConfig.java +++ b/com-marriage-client/src/main/java/com/jinrui/marriage/client/config/SecurityConfig.java @@ -95,7 +95,7 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter { // 过滤请求 .authorizeRequests() // 对于登录login 验证码captchaImage 允许匿名访问 - .antMatchers("/marriage/common/login", "/marriage/common/sms", "/marriage/ocr/**").permitAll() + .antMatchers("/marriage/common/login", "/marriage/common/sms", "/marriage/common/checkCode", "/marriage/ocr/**", "/marriage/activity/current", "/marriage/receiveCheck2").permitAll() // .antMatchers("/**", "/captchaImage").anonymous() .antMatchers( HttpMethod.GET, diff --git a/com-marriage-client/src/main/java/com/jinrui/marriage/client/controller/CommonController.java b/com-marriage-client/src/main/java/com/jinrui/marriage/client/controller/CommonController.java index e275a5e..ac10ab7 100644 --- a/com-marriage-client/src/main/java/com/jinrui/marriage/client/controller/CommonController.java +++ b/com-marriage-client/src/main/java/com/jinrui/marriage/client/controller/CommonController.java @@ -4,16 +4,15 @@ import cn.jsms.api.SendSMSResult; import cn.jsms.api.common.SMSClient; import cn.jsms.api.common.model.SMSPayload; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.jinrui.assembly.utils.DateTimeUtil; import com.jinrui.assembly.utils.RandomUtil; import com.jinrui.assembly.utils.http.HttpUtil; import com.jinrui.assembly.utils.result.ResultObject; import com.jinrui.assembly.utils.result.ResultUtil; import com.jinrui.core.consts.RedisCacheKey; import com.jinrui.core.model.MarriageLoginUser; -import com.jinrui.core.model.dto.BaseDTO; -import com.jinrui.core.model.dto.CommSmsDTO; -import com.jinrui.core.model.dto.MarrigeLoginDTO; -import com.jinrui.core.model.dto.RequestDTO; +import com.jinrui.core.model.dto.*; +import com.jinrui.core.model.entity.MarriageActivity; import com.jinrui.core.model.entity.MarriageCode; import com.jinrui.core.model.entity.MarriageSales; import com.jinrui.core.model.entity.Record; @@ -24,6 +23,7 @@ import com.jinrui.core.model.vo.ResultVO; import com.jinrui.core.model.vo.WinNoticeDetailsVO; import com.jinrui.core.model.vo.WinNoticePoolVO; import com.jinrui.core.redis.RedisCacheManager; +import com.jinrui.core.service.IMarriageActivityService; import com.jinrui.core.service.IMarriageCodeService; import com.jinrui.core.service.IMarriageSalesService; import com.jinrui.marriage.client.service.MarriageTokenService; @@ -65,6 +65,9 @@ public class CommonController { @Autowired private IMarriageCodeService iMarriageCodeService; + @Autowired + private IMarriageActivityService iMarriageActivityService; + @Value("${sms.appKey}") private String appKey; @Value("${sms.masterSecret}") @@ -89,13 +92,13 @@ public class CommonController { if (Objects.isNull(one)){ return ResultUtil.failedMessage("手机号错误!"); } - }else if("1".equals(dto.getType())){ + } else if ("1".equals(dto.getType())) { LambdaQueryWrapper queryWrapper1 = new LambdaQueryWrapper<>(); queryWrapper1.eq(MarriageCode::getCode, dto.getMobile()); queryWrapper1.orderByDesc(MarriageCode::getCreateTime); queryWrapper1.last("limit 1"); MarriageCode code1 = iMarriageCodeService.getOne(queryWrapper1); - if(Objects.nonNull(code1)){ + if (Objects.nonNull(code1)) { return ResultUtil.failedMessage("该手机号已登记!"); } } @@ -123,6 +126,50 @@ public class CommonController { return ResultUtil.success(verifyCode); } + @PostMapping("/checkCode") + public ResultObject checkCode(@RequestBody CheckCodeDto dto) { + if (StringUtils.isBlank(dto.getMobile())) { + return ResultUtil.failedMessage("请输入手机号!"); + } + if (StringUtils.isBlank(dto.getSmsCode())) { + return ResultUtil.failedMessage("验证码不能为空!"); + } + if (StringUtils.isBlank(dto.getType())) { + return ResultUtil.failedMessage("短信类型不能为空!"); + } + + String key = RedisCacheKey.VERICODE_MOBILE +dto.getType()+"-"+ dto.getMobile(); + String verifyCode = (String)redisCacheManager.getObject(RedisCacheKey.DBINDEX_DEFAULT, key); + if(!StringUtils.equals(dto.getSmsCode(), verifyCode)){ + return ResultUtil.failedMessage("验证码错误,请重新输入!"); + } + + LambdaQueryWrapper queryWrapper1 = new LambdaQueryWrapper<>(); + queryWrapper1.eq(MarriageCode::getCode, dto.getMobile()); + queryWrapper1.orderByDesc(MarriageCode::getCreateTime); + queryWrapper1.last("limit 1"); + MarriageCode code = iMarriageCodeService.getOne(queryWrapper1); + if (Objects.nonNull(code)) { + Date now = DateTimeUtil.now(); + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(MarriageActivity::getStatus, 0) + .le(MarriageActivity::getActivityStartTime, now) + .ge(MarriageActivity::getActivityEndTime, now) + .orderByDesc(MarriageActivity::getCreateTime) + .last("limit 1"); + MarriageActivity act = iMarriageActivityService.getOne(wrapper); + if (act == null) { + return ResultUtil.failedMessage("活动已过期!"); + } + if (Objects.equals(act.hashCode(), code.getCode())) { + return ResultUtil.success(code); + } + return ResultUtil.failedMessage("活动已过期!"); + + } + return ResultUtil.success(); + } + @PostMapping("/login") public ResultObject login(@RequestBody MarrigeLoginDTO dto) { diff --git a/com-marriage-client/src/main/java/com/jinrui/marriage/client/controller/MarriageController.java b/com-marriage-client/src/main/java/com/jinrui/marriage/client/controller/MarriageController.java index fac01cd..703c495 100644 --- a/com-marriage-client/src/main/java/com/jinrui/marriage/client/controller/MarriageController.java +++ b/com-marriage-client/src/main/java/com/jinrui/marriage/client/controller/MarriageController.java @@ -12,12 +12,14 @@ import com.jinrui.core.model.dto.MarriageCodeDTO; import com.jinrui.core.model.dto.MarrigeLoginDTO; import com.jinrui.core.model.entity.MarriageCode; import com.jinrui.core.model.entity.MarriageSales; +import com.jinrui.core.model.entity.MarriageActivity; import com.jinrui.core.model.vo.MarriageCodeListVO; import com.jinrui.core.model.vo.MarriageCodeVO; import com.jinrui.core.model.vo.MarriageSalesVO; import com.jinrui.core.redis.RedisCacheManager; import com.jinrui.core.service.IMarriageCodeService; import com.jinrui.core.service.IMarriageSalesService; +import com.jinrui.core.service.IMarriageActivityService; import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; @@ -44,6 +46,8 @@ public class MarriageController { private RedisCacheManager redisCacheManager; @Autowired private IMarriageCodeService iMarriageCodeService; + @Autowired + private IMarriageActivityService iMarriageActivityService; @PostMapping("/codeList") public ResultObject codeList(@RequestBody MarriageCodeDTO dto) { @@ -79,6 +83,28 @@ public class MarriageController { return ResultUtil.success(marriageCodeVO); } + @org.springframework.web.bind.annotation.GetMapping("/activity/current") + public ResultObject currentActivity() { + Date now = DateTimeUtil.now(); + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(MarriageActivity::getStatus, 0) + .le(MarriageActivity::getActivityStartTime, now) + .ge(MarriageActivity::getActivityEndTime, now) + .orderByDesc(MarriageActivity::getCreateTime) + .last("limit 1"); + MarriageActivity act = iMarriageActivityService.getOne(wrapper); + if (act == null) { + return ResultUtil.success(null); + } + java.util.Map data = new java.util.HashMap<>(); + data.put("activityName", act.getActivityName()); + data.put("activityStartTime", DateTimeUtil.formatDateTime(act.getActivityStartTime())); + data.put("activityEndTime", DateTimeUtil.formatDateTime(act.getActivityEndTime())); + data.put("money", act.getMoney()); + data.put("status", act.getStatus()); + return ResultUtil.success(data); + } + @PostMapping("/leftOverCount") public ResultObject leftOverCount() { LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); @@ -122,6 +148,72 @@ public class MarriageController { return canReceive; } + @PostMapping("/receiveCheck2") + public ResultObject receiveCheck2(@RequestBody MarriageCodeDTO dto) { + if (StringUtils.isBlank(dto.getMarriageNo())) { + return ResultUtil.failedMessage("结婚证字号不能为空!"); + } else { + int length = dto.getMarriageNo().length(); + if (length < 11) { + return ResultUtil.failedMessage("结婚证字号长度不对!"); + } else { + if (!checkMarriageNo(dto.getMarriageNo())) { + return ResultUtil.failedMessage("结婚证字号不符合活动条件!"); + } + } + } + if (StringUtils.isBlank(dto.getReceiveName())) { + return ResultUtil.failedMessage("领取人姓名不能为空!"); + } + if (StringUtils.isBlank(dto.getReceiveMobile())) { + return ResultUtil.failedMessage("领取人手机号不能为空!"); + } + + if (StringUtils.isBlank(dto.getCode())) { + return ResultUtil.failedMessage("核验码不能为空!"); + } + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.and(wrap -> { + wrap.or().eq(MarriageCode::getMarriageNo, dto.getMarriageNo()); + wrap.or().eq(MarriageCode::getReceiveMobile, dto.getReceiveMobile()); + wrap.or().eq(MarriageCode::getCode, dto.getCode()); + }); + queryWrapper.orderByDesc(MarriageCode::getCreateTime); + queryWrapper.last("limit 1"); + MarriageCode marriageCode = iMarriageCodeService.getOne(queryWrapper); + + if (Objects.nonNull(marriageCode)) { + if (dto.getReceiveMobile().equals(marriageCode.getReceiveMobile())) { + return ResultUtil.failedMessage("该领取人已领取过新婚送福活动刮刮乐!"); + } + if (dto.getMarriageNo().equals(marriageCode.getMarriageNo())) { + return ResultUtil.failedMessage("这个证号已参与过活动!"); + } + if (StringUtils.isNotBlank(marriageCode.getMarriageNo())) { + return ResultUtil.failedMessage("此代金卷已使用过!"); + } + } + + String key = RedisCacheKey.VERICODE_MOBILE + "3-" + dto.getReceiveMobile(); + String verifyCode = (String) redisCacheManager.getObject(RedisCacheKey.DBINDEX_DEFAULT, key); + if (!StringUtils.equals(dto.getSmsCode(), verifyCode)) { + return ResultUtil.failedMessage("验证码错误,请重新输入!"); + } + Date now = DateTimeUtil.now(); + marriageCode = MarriageCode.builder() + .marriageNo(dto.getMarriageNo()) + .receiveName(dto.getReceiveName()) + .code(dto.getCode()) + .receiveMobile(dto.getReceiveMobile()) + .signImage(dto.getSignImage()) + .receiveTime(now) + .salesNo(dto.getSalesNo()) + .build(); + MarriageCodeVO vo = new MarriageCodeVO(); + BeanUtils.copyProperties(marriageCode, vo); + return ResultUtil.success(vo); + } + @PostMapping("/receiveCheck") public ResultObject receiveCheck(@RequestBody MarriageCodeDTO dto) { if (StringUtils.isBlank(dto.getMarriageNo())) { @@ -305,4 +397,3 @@ public class MarriageController { } } - diff --git a/com-marriage-client/src/main/java/com/jinrui/marriage/client/controller/OcrController.java b/com-marriage-client/src/main/java/com/jinrui/marriage/client/controller/OcrController.java index 35aafc9..7276a91 100644 --- a/com-marriage-client/src/main/java/com/jinrui/marriage/client/controller/OcrController.java +++ b/com-marriage-client/src/main/java/com/jinrui/marriage/client/controller/OcrController.java @@ -76,7 +76,7 @@ public class OcrController { return ResultUtil.failedMessage("上传标识不能为空!"); } - String smsKey = RedisCacheKey.VERICODE_MOBILE + "2-" + dto.getMobile(); + String smsKey = RedisCacheKey.VERICODE_MOBILE + "3-" + dto.getMobile(); String verifyCode = (String) redisCacheManager.getObject(RedisCacheKey.DBINDEX_DEFAULT, smsKey); if (!StringUtils.equals(dto.getSmsCode(), verifyCode)) { return ResultUtil.failedMessage("验证码错误,请重新输入!");