资讯详情

大神接单订单防重复下单方案分享

📅 2026/10/23 11:00:03 | 华诺云谱 👁 阅读
大神接单订单防重复下单方案分享
大神接单订单防重复下单方案分享在电竞大神接单小程序场景里用户连续点击提交、网络抖动、网关重试、支付回调重复推送都可能触发重复下单产生多笔同需求订单进而引发重复扣费、多派单、佣金结算错乱、售后纠纷等问题。很多项目只依靠前端按钮置灰做拦截很容易被绕过。本文分享一套前端拦截Redis令牌校验数据库兜底的多层防重复下单方案保障下单接口幂等。后端基于SpringBoot MyBatis-Plus开发Redis存储幂等令牌使用Lua脚本实现原子校验与删除MySQL订单表增加唯一索引兜底。下单链路分为预生成令牌、提交校验、创建订单三层校验层层拦截重复请求。整体方案分为四层防护前端防抖提交后按钮置灰短时间禁止再次点击作为第一层软拦截幂等Token校验进入下单确认页时获取唯一令牌提交下单携带令牌Redis原子校验消费业务维度锁同一用户、同一大神、同一服务在短时间内加分布式锁防止并发重复提交数据库唯一索引兜底订单请求号设置唯一约束拦截穿透上层校验的重复写入。业务流程用户打开下单确认页 → 请求接口生成幂等Token存入Redis → 前端提交下单携带Token和业务参数 → 后端执行Lua脚本校验Token校验通过直接删除Token → 校验成功后执行业务创建订单校验失败直接返回重复提交提示。下面是订单实体和幂等工具核心代码示例Data TableName(t_player_order) public class PlayerOrder { private Long id; // 业务请求幂等号 private String requestNo; private String orderNo; private Long userId; private Long playerId; private String gameCode; private Long serviceId; private BigDecimal orderAmount; private Integer orderStatus; private LocalDateTime createTime; } Component public class IdempotentTokenService { Autowired private StringRedisTemplate redisTemplate; private static final String TOKEN_PREFIX idempotent:order:token:; private static final long EXPIRE_SECONDS 300; /** * 生成幂等Token */ public String generateToken() { String token UUID.randomUUID().toString().replace(-, ); redisTemplate.opsForValue().set(TOKEN_PREFIX token, 1, EXPIRE_SECONDS, TimeUnit.SECONDS); return token; } /** * Lua脚本原子校验并删除token */ public boolean checkToken(String token) { String key TOKEN_PREFIX token; String script if redis.call(GET,KEYS[1]) ARGV[1] then return redis.call(DEL,KEYS[1]) else return 0 end; DefaultRedisScriptLong redisScript new DefaultRedisScript(script, Long.class); Long result redisTemplate.execute(redisScript, Collections.singletonList(key), 1); return result ! null result 0; } }下单接口层先调用checkToken校验令牌校验不通过直接返回“请勿重复提交订单”。令牌校验通过之后再尝试获取业务分布式锁锁key使用lock:order:user:userId:playerId:serviceId锁定时长控制在几秒用来挡住同一用户对同一个大神服务的并发请求。Service public class OrderCreateService { Autowired private IdempotentTokenService idempotentTokenService; Autowired private StringRedisTemplate redisTemplate; public void createOrder(OrderCreateDTO dto) { boolean pass idempotentTokenService.checkToken(dto.getToken()); if (!pass) { throw new RuntimeException(请勿重复提交订单); } String lockKey lock:order: dto.getUserId() : dto.getPlayerId() : dto.getServiceId(); Boolean lock redisTemplate.opsForValue().setIfAbsent(lockKey, 1, 5, TimeUnit.SECONDS); if (Boolean.FALSE.equals(lock)) { throw new RuntimeException(订单提交中请勿频繁操作); } try { // 组装订单、入库逻辑 } finally { redisTemplate.delete(lockKey); } } }数据库兜底机制是最后一道防线。订单表的request_no字段建立唯一索引就算Redis异常、令牌校验失效重复插入相同requestNo时数据库抛出唯一键冲突异常代码捕获异常后查询已有订单返回不会生成多条重复订单。requestNo可以由前端携带或者后端随Token一起生成一单对应唯一请求号。支付回调场景同样需要幂等处理。支付渠道会存在多次回调通知不能重复更新订单状态、重复发放权益。以业务订单号作为幂等key回调进来先查询订单状态如果已经是已支付直接返回成功不再执行业务逻辑。落地时需要注意几个细节Token设置合理过期时间下单超时未提交自动失效用户重新进入页面会获取新Token分布式锁不能设置过长时间防止业务异常锁死Redis做好降级预案如果Redis服务不可用依赖数据库唯一索引兜底。风控层面增加监控短时间内多次触发重复提交拦截的用户后台进行预警识别脚本刷单、恶意请求行为。所有重复拦截记录写入日志方便问题排查区分是用户操作问题还是接口重试导致。这套方案的核心思路是前端减负、Redis原子校验防并发、数据库兜底防数据错乱。三层防护互相配合既满足正常用户操作体验又能挡住网络重试、恶意刷请求带来的重复下单问题。后续还可以扩展全局幂等注解统一接入所有写类型接口。
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。

↑