支付接口幂等性(精简版)

接口幂等性概念

定义:用户对同一操作发起一次或多次请求的结果一致,多次调用不会改变业务状态,确保重复调用与单次调用结果相同。


使用场景

  1. 前端重复提交:用户多次点击提交按钮

  2. 接口超时重试:网络波动导致客户端自动重试

  3. 消息重复消费:消息队列因ACK机制触发消息重复投递


实现方法

1. Token 机制

流程

  1. 客户端首次请求获取 Token

    • 服务端生成全局唯一 ID 作为 Token(如百度的 uid-generator、美团的 Leaf

    • Token 存储至 Redis,并返回给客户端

  2. 客户端二次请求携带此 Token

  3. 服务端校验 Token:

    • 存在:执行业务逻辑,删除 Redis 中的 Token

    • 不存在:判定为重复请求,直接返回结果

注意事项

  • 原子性操作:Token 校验与删除建议通过 Lua 脚本实现

  • Key 设计业务前缀 + 唯一标识(如 fruit_milk_device:jwt_token


2. Redis 的 SETNX 命令(分布式锁)

流程

  1. 客户端发起请求,生成唯一业务标识(如用户ID+时间戳)

  2. 执行 SETNX key value

    • 成功(返回1):执行业务,设置超时时间(如 expire key 30

    • 失败(返回0):判定为重复请求,直接返回

项目实践示例

  • 场景:学生一卡通支付(食堂刷卡)

  • 实现

    1. 请求参数加密(RSA 防篡改)

    2. 校验请求时间有效性(如时间差超过1分钟则拒绝)

    3. 执行原子操作:

      Boolean flag = redisTemplate.opsForValue().setIfAbsent(
          "nx:" + key, // Key 示例:一卡通卡号
          key, 
          Long.valueOf(repeatSwipeInterval), 
          TimeUnit.SECONDS
      );

项目实践:Token 机制案例

需求背景:水果奶下单支付(学生选择方案后支付)
实现步骤

  1. 生成校验码

    • 客户端调用校验接口,服务端通过 IdUtils.fastUUID() 生成随机校验码

    • Redis 存储 Key:fruit_milk_device:jwt_token,Value:校验码

  2. 下单请求校验

    • 客户端携带校验码(Header 中)

    • 服务端从 Redis 查询校验码:

      • 不存在:抛出「非法请求」异常

      • 存在:执行支付流程

  3. 支付并发控制

    • 方案1(推荐):数据库原子操作

      UPDATE fruit_milk_account 
      SET balance = balance - #{money} 
      WHERE account_id = #{accountId} AND balance >= #{money}
    • 方案2:Redis 分布式锁 + 乐观锁

      // 1. 获取锁
      boolean lock = redisService.tryLock(lockKey);  
      // 2. 查询并扣减余额
      FruitMilkAccount account = queryAccount(accountId);  
      account.setBalance(account.getBalance() - money);  
      // 3. 乐观锁更新
      boolean updated = updateById(account);  
      if (!updated) throw new RuntimeException("余额更新失败");  
      // 4. 释放锁
      redisService.releaseLock(lockKey);  

关键总结

  1. Token 机制:适用于需严格一次性验证的场景(如支付)

  2. SETNX 分布式锁:适合高频短时操作(如秒杀)

  3. 原子性保障:优先使用数据库原子操作,高并发场景结合 Redis 锁与乐观锁

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值