Flutter API幂等接口处理:连接超时引发重复请求问题
支付后商品购买API超时的重复下单问题
按钮点击流程:先调用支付API完成用户向我方转账,随后调用商品购买API。当前存在的问题:
- 支付API可正常执行,但商品购买API可能出现连接超时,分两种场景:
- 超时后用户未获得商品
- 超时后用户已获得商品,但我方未收到购买成功响应(对方先发放商品再返回响应),无法确认购买状态
- 现有重试函数无限制递归调用,极易导致用户被重复下单,代码如下:
Future<Response> testDisconnect(back) async { debugPrint("meeow"); debugPrint(back); try { return await dio.post("apiurl", data: {"me": ",e"}, options: Options( headers: { 'Content-Type': 'application/json', 'Accept': 'application/json' }, )); } on DioException catch (e) { debugPrint(e.type.toString()); return testDisconnect(back); } }
优化方案
1. 给重试添加次数限制与退避策略
取消无限制递归,设定最大重试次数,同时采用指数退避策略(每次重试间隔递增),避免短时间内重复请求加重服务端压力,降低重复下单风险。
修改后的示例代码:
Future<Response> testDisconnect(String back, {int retryCount = 0, int maxRetries = 3}) async { debugPrint("meeow"); debugPrint(back); try { return await dio.post("apiurl", data: {"me": ",e"}, options: Options( headers: { 'Content-Type': 'application/json', 'Accept': 'application/json' }, )); } on DioException catch (e) { debugPrint(e.type.toString()); // 仅针对连接超时/连接错误进行重试 if (e.type == DioExceptionType.connectionTimeout || e.type == DioExceptionType.connectionError) { if (retryCount < maxRetries) { // 指数退避:间隔依次为1s、2s、4s await Future.delayed(Duration(seconds: 1 << retryCount)); return testDisconnect(back, retryCount: retryCount + 1, maxRetries: maxRetries); } } // 超出重试次数或非可重试错误,直接抛出异常 throw e; } }
2. 实现幂等请求机制
要求商品购买API支持幂等,确保相同请求多次调用仅产生一次效果:
- 每次发起购买请求时,生成唯一
requestId(如UUID),作为请求参数传入 - 对方服务维护已处理
requestId列表,收到重复请求时直接返回历史成功响应,不再重复发放商品
3. 增加状态查询前置步骤
当购买API超时后,优先调用商品状态查询API:
- 若查询到用户已获得商品,直接终止流程
- 若查询到未获得商品,再执行有限次数的重试
- 若查询API也超时,再触发退避重试逻辑
4. 本地记录请求状态
发起购买请求前,在本地存储(如数据库、SharedPreferences)记录requestId与请求状态(待处理/处理中/成功/失败):
- 请求发起时标记为“处理中”
- 收到成功响应后更新为“成功”
- 超时后先校验本地状态,结合查询API结果判断是否重试,避免重复发起请求
内容的提问来源于stack exchange,提问作者Navy Divine
相关产品推荐
相关产品推荐

