feat(order): 优化预约与取消流程,增强幂等与锁机制
- 对预约流程新增数据库校验服务编码,提取对应AES密钥解密请求参数 - 新增基于权益码的分布式锁,防止并发重复提交,锁未获取时返回错误 - 调整幂等校验逻辑,准确区分已预约、已取消、已完成等状态返回对应响应 - 调整权益码过期及渠道相关的错误返回信息,提升用户提示准确性 - 增加预约流程中锁的defer释放,确保流程结束自动释放锁资源 - 预约流程新增调用蓝色兄弟券码接口,支持幂等和超时处理 - 取消流程新增分布式锁控制,对订单状态进行更细化判定及返回 - 取消作废逻辑完善,失败时查询券码状态确认后续处理 - 完善预约和取消流程步骤及验收标准,新增并发和锁竞争等测试用例 - 更新相关API文档及流程图,补充异常场景处理说明 - 在docs中新增AES加解密算法支持AES,完善对账及安全模块说明
This commit is contained in:
parent
1d123399f6
commit
0fcbaf8079
224
docs/需求文档-PRD.md
224
docs/需求文档-PRD.md
|
|
@ -27,7 +27,7 @@
|
|||
│ ├── 对账文件下载
|
||||
│ └── 对账数据核对
|
||||
└── 安全与加密模块
|
||||
├── SM2/SM4加解密(邮储银行)
|
||||
├── SM2/SM4/AES加解密(邮储银行)
|
||||
├── RSA/AES加解密(蓝色兄弟)
|
||||
└── 签名验签
|
||||
```
|
||||
|
|
@ -89,28 +89,36 @@
|
|||
**功能描述**:接收邮储银行服务开放平台的预约请求,为客户预约虚拟商品充值服务
|
||||
|
||||
**业务规则**:
|
||||
1. 对request进行AES解密,解析出type(服务编码)、code(权益码)、mac(客户id)
|
||||
2. 对code(权益码)进行幂等验证:
|
||||
1. 查询数据库验证服务编码(type)是否存在(数据库中维护邮储服务编码与营销平台活动的映射关系)
|
||||
- 如果不存在:返回"暂不支持此服务"
|
||||
- 如果存在:获取对应的AES加密密钥(aes_key)和向量(aes_iv),用于后续解密
|
||||
2. 使用从数据库查询到的aes_key和aes_iv对request进行AES解密,解析出type(服务编码)、code(权益码)、mac(客户id)
|
||||
- 解密失败:返回"参数错误"
|
||||
3. 基于权益码(code)获取分布式锁,防止重复请求:
|
||||
- 获取锁成功:继续执行后续流程
|
||||
- 获取锁失败:返回"请勿重复提交"
|
||||
4. 对code(权益码)进行幂等验证:
|
||||
- 若订单状态为「服务已预约(200)」,直接返回预约成功(与正常请求返回一致)
|
||||
- 若订单状态为「服务未预约(100)」,继续执行后续流程(更新订单,不新增)
|
||||
- 若订单状态为其他状态,返回服务已预约
|
||||
3. 查询数据库验证服务编码(type)是否存在(数据库中维护邮储服务编码与营销平台活动的映射关系)
|
||||
如果不存在 返回暂不支持此服务
|
||||
4. 请求邮储服务开放平台接口验证权益码是否过期
|
||||
- 若订单状态为「服务已取消(400)」,返回"服务已取消"
|
||||
- 若订单状态为「服务已完成(300)」,返回"服务已生效"
|
||||
5. 请求邮储服务开放平台接口验证权益码是否过期
|
||||
如果过期:
|
||||
1、CRM渠道返回 "二维码20分钟内有效,现已超时失效,请联系理财经理重新生成二维码!
|
||||
2、手机银行渠道返回 “当前页面停置时间过长,请您重新进入该页面”
|
||||
5. 创建/更新订单记录(订单状态:服务未预约)
|
||||
6. 请求邮储服务开放平台接口发起预约:
|
||||
- 预约成功或返回161010(交易已预约):继续执行步骤7
|
||||
2、手机银行渠道返回 "当前页面停置时间过长,请您重新进入该页面"
|
||||
6. 创建/更新订单记录(订单状态:服务未预约)
|
||||
7. 请求邮储服务开放平台接口发起预约:
|
||||
- 预约成功或返回161010(交易已预约):继续执行步骤8
|
||||
- 其他情况:订单状态保持「服务未预约(100)」,返回预约失败
|
||||
7. 请求蓝色兄弟营销平台获取券码链接(使用相同交易号和参数请求):
|
||||
8. 请求蓝色兄弟营销平台获取券码链接(使用相同交易号和参数请求):
|
||||
- 请求成功:更新订单状态为「服务已预约(200)」,返回预约成功响应
|
||||
- 请求异常:订单状态保持「服务未预约(100)」,返回预约失败
|
||||
9. 释放分布式锁
|
||||
|
||||
**输入**:
|
||||
| 字段 | 类型 | 必填 | 说明 |
|
||||
|-----|------|-----|------|
|
||||
| type | String | M | 服务编码,用于查询数据库获取AES解密密钥 |
|
||||
| request | String | M | AES加密字符串,解密后格式:type=服务编码&code=权益码&mac=加密后的客户id |
|
||||
| channel | String | M | 渠道标识:12-手机银行,17-电话银行,41-CRM零售 |
|
||||
| tranChnl | String | M | 渠道标识:12-手机银行,17-电话银行,41-CRM零售 |
|
||||
|
|
@ -127,12 +135,15 @@
|
|||
| backUrl | String | C | 返回手机银行的地址 |
|
||||
|
||||
**验收标准**:
|
||||
- [ ] 能正确解密AES加密的request参数
|
||||
- [ ] 入参type(服务编码)为必填字段,缺失时返回"参数错误"
|
||||
- [ ] 根据入参type查询数据库获取对应的aes_key和aes_iv
|
||||
- [ ] 服务编码(type)不存在时,返回"暂不支持此服务"(在AES解密之前校验)
|
||||
- [ ] 使用数据库查询到的aes_key和aes_iv能正确解密AES加密的request参数
|
||||
- [ ] 能正确解析解密后的参数(type、code、mac)
|
||||
- [ ] 幂等验证:相同权益码(code)状态为「服务已预约(200)」时,直接返回预约成功
|
||||
- [ ] 幂等验证:相同权益码(code)状态为「服务未预约(100)」时,继续执行后续流程
|
||||
- [ ] 幂等验证:相同权益码(code)状态为其他状态时,返回"服务已预约"
|
||||
- [ ] 服务编码(type)不存在时,返回"暂不支持此服务"
|
||||
- [ ] 幂等验证:相同权益码(code)状态为「已取消(400)」时,返回"服务已取消"
|
||||
- [ ] 幂等验证:相同权益码(code)状态为「已完成(300)」时,返回"服务已生效"
|
||||
- [ ] 权益码过期且渠道为CRM(41)时,返回"二维码20分钟内有效,现已超时失效,请联系理财经理重新生成二维码"
|
||||
- [ ] 权益码过期且渠道为手机银行(12)时,返回"当前页面停置时间过长,请您重新进入该页面"
|
||||
- [ ] 订单创建/更新时初始状态为「服务未预约(100)」
|
||||
|
|
@ -142,36 +153,41 @@
|
|||
- [ ] 蓝色兄弟券码获取异常时,订单状态保持「服务未预约(100)」,返回预约失败
|
||||
- [ ] 预约成功后返回蓝色兄弟兑换地址(url)
|
||||
- [ ] 响应正确透传tranChnl、instType、backUrl字段
|
||||
- [ ] 并发请求时,基于权益码获取分布式锁,获取失败返回"请勿重复提交"
|
||||
|
||||
**测试用例**:
|
||||
|
||||
| 用例编号 | 测试场景 | 前置条件 | 输入数据 | 预期结果 |
|
||||
|---------|---------|---------|---------|----------|
|
||||
| TC-3.1.1-001 | 正常预约成功 | 服务编码存在、权益码有效、订单不存在 | request=有效加密参数, channel=12 | code=0, 返回url、tranChnl、instType、backUrl |
|
||||
| TC-3.1.1-002 | AES解密失败 | - | request=无效加密字符串 | code=2, msg="参数错误" |
|
||||
| TC-3.1.1-003 | 参数解析失败-缺少type | - | request解密后无type字段 | code=2, msg="参数错误" |
|
||||
| TC-3.1.1-004 | 参数解析失败-缺少code | - | request解密后无code字段 | code=2, msg="参数错误" |
|
||||
| TC-3.1.1-005 | 幂等-已预约状态 | 订单状态=200(已预约) | 相同权益码再次请求 | code=0, 返回原预约成功响应 |
|
||||
| TC-3.1.1-006 | 幂等-未预约状态 | 订单状态=100(未预约) | 相同权益码再次请求 | 继续执行流程,最终返回预约结果 |
|
||||
| TC-3.1.1-007 | 幂等-已完成状态 | 订单状态=300(已完成) | 相同权益码再次请求 | code=4, msg="服务已预约" |
|
||||
| TC-3.1.1-008 | 幂等-已取消状态 | 订单状态=400(已取消) | 相同权益码再次请求 | code=4, msg="服务已预约" |
|
||||
| TC-3.1.1-009 | 服务编码不存在 | 数据库无该服务编码映射 | type=999999 | code=4, msg="暂不支持此服务" |
|
||||
| TC-3.1.1-010 | 权益码过期-CRM渠道 | 邮储返回权益码已过期 | channel=41 | code=4, msg含"二维码20分钟内有效" |
|
||||
| TC-3.1.1-011 | 权益码过期-手机银行 | 邮储返回权益码已过期 | channel=12 | code=4, msg含"当前页面停置时间过长" |
|
||||
| TC-3.1.1-012 | 权益码过期-电话银行 | 邮储返回权益码已过期 | channel=17 | code=4, msg含"当前页面停置时间过长" |
|
||||
| TC-3.1.1-013 | 邮储预约成功 | 权益码有效 | 正常请求 | 继续调用蓝色兄弟获取券码 |
|
||||
| TC-3.1.1-014 | 邮储返回已预约(161010) | 权益码有效 | 正常请求 | 继续调用蓝色兄弟获取券码 |
|
||||
| TC-3.1.1-015 | 邮储预约失败 | 邮储返回其他错误 | 正常请求 | code!=0, 订单状态=100 |
|
||||
| TC-3.1.1-016 | 券码获取成功 | 邮储预约成功 | 正常请求 | code=0, 订单状态=200, 返回url |
|
||||
| TC-3.1.1-017 | 券码获取失败 | 蓝色兄弟返回异常 | 正常请求 | code!=0, 订单状态=100 |
|
||||
| TC-3.1.1-018 | 券码获取超时 | 蓝色兄弟接口超时 | 正常请求 | code!=0, 订单状态=100 |
|
||||
| TC-3.1.1-019 | backUrl为空 | backUrl参数未传 | backUrl=空 | code=0, 响应中backUrl为空 |
|
||||
| TC-3.1.1-020 | 必填参数缺失-channel | - | 不传channel | code=2, msg="参数错误" |
|
||||
| TC-3.1.1-021 | 必填参数缺失-tranChnl | - | 不传tranChnl | code=2, msg="参数错误" |
|
||||
| TC-3.1.1-022 | 必填参数缺失-instType | - | 不传instType | code=2, msg="参数错误" |
|
||||
| TC-3.1.1-023 | 邮储服务不可用 | 邮储平台异常 | 正常请求 | code=1, msg="系统异常" |
|
||||
| TC-3.1.1-024 | 蓝色兄弟服务不可用 | 蓝色兄弟平台异常 | 正常请求 | code=1, 订单状态=100 |
|
||||
| TC-3.1.1-025 | 并发幂等测试 | 同一权益码 | 同时发起多个请求 | 仅一个成功创建订单,其他返回幂等结果 |
|
||||
| TC-3.1.1-001 | 正常预约成功 | 服务编码存在、权益码有效、订单不存在 | type=有效服务编码, request=有效加密参数, channel=12 | code=0, 返回url、tranChnl、instType、backUrl |
|
||||
| TC-3.1.1-002 | 必填参数缺失-type | - | 不传type | code=2, msg="参数错误" |
|
||||
| TC-3.1.1-003 | 服务编码不存在 | 数据库无该服务编码映射 | type=999999 | code=4, msg="暂不支持此服务"(在AES解密前返回) |
|
||||
| TC-3.1.1-004 | AES解密失败-密钥不匹配 | 服务编码存在但request用其他密钥加密 | type=有效服务编码, request=用错误密钥加密 | code=2, msg="参数错误" |
|
||||
| TC-3.1.1-005 | AES解密失败-格式错误 | 服务编码存在 | type=有效服务编码, request=无效加密字符串 | code=2, msg="参数错误" |
|
||||
| TC-3.1.1-006 | 参数解析失败-解密后缺少type | 服务编码存在,AES解密成功 | request解密后无type字段 | code=2, msg="参数错误" |
|
||||
| TC-3.1.1-007 | 参数解析失败-解密后缺少code | 服务编码存在,AES解密成功 | request解密后无code字段 | code=2, msg="参数错误" |
|
||||
| TC-3.1.1-008 | 幂等-已预约状态 | 订单状态=200(已预约) | 相同权益码再次请求 | code=0, 返回原预约成功响应 |
|
||||
| TC-3.1.1-009 | 幂等-未预约状态 | 订单状态=100(未预约) | 相同权益码再次请求 | 继续执行流程,最终返回预约结果 |
|
||||
| TC-3.1.1-010 | 幂等-已完成状态 | 订单状态=300(已完成) | 相同权益码再次请求 | code=4, msg="服务已生效" |
|
||||
| TC-3.1.1-011 | 幂等-已取消状态 | 订单状态=400(已取消) | 相同权益码再次请求 | code=4, msg="服务已取消" |
|
||||
| TC-3.1.1-012 | 权益码过期-CRM渠道 | 邮储返回权益码已过期 | channel=41 | code=4, msg含"二维码20分钟内有效" |
|
||||
| TC-3.1.1-013 | 权益码过期-手机银行 | 邮储返回权益码已过期 | channel=12 | code=4, msg含"当前页面停置时间过长" |
|
||||
| TC-3.1.1-014 | 权益码过期-电话银行 | 邮储返回权益码已过期 | channel=17 | code=4, msg含"当前页面停置时间过长" |
|
||||
| TC-3.1.1-015 | 邮储预约成功 | 权益码有效 | 正常请求 | 继续调用蓝色兄弟获取券码 |
|
||||
| TC-3.1.1-016 | 邮储返回已预约(161010) | 权益码有效 | 正常请求 | 继续调用蓝色兄弟获取券码 |
|
||||
| TC-3.1.1-017 | 邮储预约失败 | 邮储返回其他错误 | 正常请求 | code!=0, 订单状态=100 |
|
||||
| TC-3.1.1-018 | 券码获取成功 | 邮储预约成功 | 正常请求 | code=0, 订单状态=200, 返回url |
|
||||
| TC-3.1.1-019 | 券码获取失败 | 蓝色兄弟返回异常 | 正常请求 | code!=0, 订单状态=100 |
|
||||
| TC-3.1.1-020 | 券码获取超时 | 蓝色兄弟接口超时 | 正常请求 | code!=0, 订单状态=100 |
|
||||
| TC-3.1.1-021 | backUrl为空 | backUrl参数未传 | backUrl=空 | code=0, 响应中backUrl为空 |
|
||||
| TC-3.1.1-022 | 必填参数缺失-channel | - | 不传channel | code=2, msg="参数错误" |
|
||||
| TC-3.1.1-023 | 必填参数缺失-tranChnl | - | 不传tranChnl | code=2, msg="参数错误" |
|
||||
| TC-3.1.1-024 | 必填参数缺失-instType | - | 不传instType | code=2, msg="参数错误" |
|
||||
| TC-3.1.1-025 | 邮储服务不可用 | 邮储平台异常 | 正常请求 | code=1, msg="系统异常" |
|
||||
| TC-3.1.1-026 | 蓝色兄弟服务不可用 | 蓝色兄弟平台异常 | 正常请求 | code=1, 订单状态=100 |
|
||||
| TC-3.1.1-027 | 并发幂等测试 | 同一权益码 | 同时发起多个请求 | 仅一个成功创建订单,其他返回幂等结果 |
|
||||
| TC-3.1.1-028 | 并发锁竞争-获取锁失败 | 同一权益码并发请求 | 第二个请求 | code=1, msg="请勿重复提交" |
|
||||
| TC-3.1.1-029 | 不同服务编码使用不同密钥 | 数据库存在多个服务编码配置 | type=服务A, request=用服务A密钥加密 | code=0, 使用服务A的aes_key/aes_iv解密成功 |
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -181,16 +197,22 @@
|
|||
|
||||
**业务规则**:
|
||||
1. 对request进行AES解密,解析出type(服务编码)、code(权益码)、mac(客户id)
|
||||
2. 检查订单状态必须是已预约状态才能取消,否则提示"服务已生效无法取消"
|
||||
3. 调用高端客户权益积分预约服务状态查询接口查询状态:
|
||||
2. 基于权益码(code)获取分布式锁,防止重复请求:
|
||||
- 获取锁成功:继续执行后续流程
|
||||
- 获取锁失败:返回"请勿重复提交"
|
||||
3. 检查订单状态必须是已预约状态才能取消:
|
||||
- 如果是已取消状态,直接返回取消成功
|
||||
- 其他非已预约状态,提示"服务已生效无法取消"
|
||||
4. 调用高端客户权益积分预约服务状态查询接口查询状态:
|
||||
- 如果不是已预约状态且不是已取消状态,提示"服务已生效,无法取消"
|
||||
- 如果是已取消状态,直接返回取消成功
|
||||
4. 调用蓝色兄弟作废接口发起作废:
|
||||
5. 调用蓝色兄弟作废接口发起作废:
|
||||
- 只有当业务码返回作废成功才算成功
|
||||
- 其他情况(如HTTP响应超时)均视为作废失败
|
||||
- 作废失败后调用蓝色兄弟券码查询接口查询券码状态,如果是已作废则按作废成功处理,否则提示"服务取消失败,请重试"
|
||||
5. 调用邮储接口发起预约取消,业务码明确返回取消成功才算成功,否则提示"服务取消失败"
|
||||
6. 订单状态更新为"已取消"(400)
|
||||
6. 调用邮储接口发起预约取消,业务码明确返回取消成功才算成功,否则提示"服务取消失败"
|
||||
7. 订单状态更新为"已取消"(400)
|
||||
8. 释放分布式锁
|
||||
|
||||
**输入**:
|
||||
| 字段 | 类型 | 必填 | 说明 |
|
||||
|
|
@ -211,7 +233,8 @@
|
|||
|
||||
**验收标准**:
|
||||
- [ ] 正确解析AES加密的request参数,提取type、code、mac字段
|
||||
- [ ] 本地订单状态非"已预约"时返回"服务已生效无法取消"
|
||||
- [ ] 本地订单状态为已取消时,直接返回取消成功
|
||||
- [ ] 本地订单状态非已预约且非已取消时,返回"服务已生效无法取消"
|
||||
- [ ] 调用邮储预约服务状态查询接口,非已预约且非已取消状态时返回"服务已生效,无法取消"
|
||||
- [ ] 调用邮储预约服务状态查询接口,已取消状态时直接返回取消成功
|
||||
- [ ] 蓝色兄弟作废接口返回作废成功时正常处理
|
||||
|
|
@ -220,6 +243,7 @@
|
|||
- [ ] 邮储预约取消接口返回成功时正常处理
|
||||
- [ ] 邮储预约取消接口返回失败时提示"服务取消失败"
|
||||
- [ ] 取消成功后订单状态更新为400
|
||||
- [ ] 并发请求时,基于权益码获取分布式锁,获取失败返回"请勿重复提交"
|
||||
|
||||
**测试用例**:
|
||||
|
||||
|
|
@ -227,18 +251,20 @@
|
|||
|---------|---------|---------|---------|----------|
|
||||
| TC-3.1.2-001 | 正常取消成功 | 订单状态=已预约(200),邮储状态=已预约,蓝色兄弟作废成功,邮储取消成功 | request=有效加密参数 | code=0, 订单状态=400 |
|
||||
| TC-3.1.2-002 | AES解密失败 | - | request=无效加密字符串 | code=2, msg="参数错误" |
|
||||
| TC-3.1.2-003 | 本地订单状态非已预约 | 订单状态=已完成(300) | request=有效加密参数 | code=1, msg="服务已生效无法取消" |
|
||||
| TC-3.1.2-004 | 本地订单不存在 | 订单不存在 | request=有效加密参数 | code=1, msg="订单不存在" |
|
||||
| TC-3.1.2-005 | 邮储查询状态-已取消 | 订单状态=已预约(200),邮储状态=已取消 | request=有效加密参数 | code=0, 直接返回取消成功 |
|
||||
| TC-3.1.2-006 | 邮储查询状态-已生效 | 订单状态=已预约(200),邮储状态=已生效 | request=有效加密参数 | code=1, msg="服务已生效,无法取消" |
|
||||
| TC-3.1.2-007 | 蓝色兄弟作废成功 | 邮储状态=已预约,蓝色兄弟作废返回成功 | request=有效加密参数 | 继续执行邮储取消流程 |
|
||||
| TC-3.1.2-008 | 蓝色兄弟作废超时后查询已作废 | 蓝色兄弟作废超时,券码查询状态=已作废(3) | request=有效加密参数 | 按作废成功处理,继续执行 |
|
||||
| TC-3.1.2-009 | 蓝色兄弟作废失败后查询已作废 | 蓝色兄弟作废返回失败,券码查询状态=已作废(3) | request=有效加密参数 | 按作废成功处理,继续执行 |
|
||||
| TC-3.1.2-010 | 蓝色兄弟作废失败且券码未作废 | 蓝色兄弟作废失败,券码查询状态=未作废 | request=有效加密参数 | code=1, msg="服务取消失败,请重试" |
|
||||
| TC-3.1.2-011 | 邮储预约取消成功 | 蓝色兄弟作废成功,邮储取消返回成功 | request=有效加密参数 | code=0, 订单状态=400 |
|
||||
| TC-3.1.2-012 | 邮储预约取消失败 | 蓝色兄弟作废成功,邮储取消返回失败 | request=有效加密参数 | code=1, msg="服务取消失败" |
|
||||
| TC-3.1.2-013 | 邮储预约取消超时 | 蓝色兄弟作废成功,邮储取消超时 | request=有效加密参数 | code=1, msg="服务取消失败" |
|
||||
| TC-3.1.2-014 | 幂等性测试-已取消订单 | 订单状态=已取消(400) | 重复发起取消请求 | code=0, 直接返回取消成功 |
|
||||
| TC-3.1.2-003 | 本地订单状态已取消 | 订单状态=已取消(400) | request=有效加密参数 | code=0, 直接返回取消成功 |
|
||||
| TC-3.1.2-004 | 本地订单状态非已预约 | 订单状态=已完成(300) | request=有效加密参数 | code=1, msg="服务已生效无法取消" |
|
||||
| TC-3.1.2-005 | 本地订单不存在 | 订单不存在 | request=有效加密参数 | code=1, msg="订单不存在" |
|
||||
| TC-3.1.2-006 | 邮储查询状态-已取消 | 订单状态=已预约(200),邮储状态=已取消 | request=有效加密参数 | code=0, 直接返回取消成功 |
|
||||
| TC-3.1.2-007 | 邮储查询状态-已生效 | 订单状态=已预约(200),邮储状态=已生效 | request=有效加密参数 | code=1, msg="服务已生效,无法取消" |
|
||||
| TC-3.1.2-008 | 蓝色兄弟作废成功 | 邮储状态=已预约,蓝色兄弟作废返回成功 | request=有效加密参数 | 继续执行邮储取消流程 |
|
||||
| TC-3.1.2-009 | 蓝色兄弟作废超时后查询已作废 | 蓝色兄弟作废超时,券码查询状态=已作废(3) | request=有效加密参数 | 按作废成功处理,继续执行 |
|
||||
| TC-3.1.2-010 | 蓝色兄弟作废失败后查询已作废 | 蓝色兄弟作废返回失败,券码查询状态=已作废(3) | request=有效加密参数 | 按作废成功处理,继续执行 |
|
||||
| TC-3.1.2-011 | 蓝色兄弟作废失败且券码未作废 | 蓝色兄弟作废失败,券码查询状态=未作废 | request=有效加密参数 | code=1, msg="服务取消失败,请重试" |
|
||||
| TC-3.1.2-012 | 邮储预约取消成功 | 蓝色兄弟作废成功,邮储取消返回成功 | request=有效加密参数 | code=0, 订单状态=400 |
|
||||
| TC-3.1.2-013 | 邮储预约取消失败 | 蓝色兄弟作废成功,邮储取消返回失败 | request=有效加密参数 | code=1, msg="服务取消失败" |
|
||||
| TC-3.1.2-014 | 邮储预约取消超时 | 蓝色兄弟作废成功,邮储取消超时 | request=有效加密参数 | code=1, msg="服务取消失败" |
|
||||
| TC-3.1.2-015 | 幂等性测试-已取消订单 | 订单状态=已取消(400) | 重复发起取消请求 | code=0, 直接返回取消成功 |
|
||||
| TC-3.1.2-016 | 并发锁竞争-获取锁失败 | 同一权益码并发请求 | 第二个请求 | code=1, msg="请勿重复提交" |
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -874,28 +900,48 @@ skinparam ActivityFontSize 12
|
|||
|
||||
start
|
||||
|
||||
:AES解密request;
|
||||
:根据入参type(服务编码)\n查询数据库;
|
||||
|
||||
if (服务编码是否存在?) then (不存在)
|
||||
:返回"暂不支持此服务";
|
||||
stop
|
||||
else (存在)
|
||||
:获取对应的aes_key和aes_iv;
|
||||
endif
|
||||
|
||||
:使用aes_key和aes_iv\n对request进行AES解密;
|
||||
|
||||
if (解密成功?) then (否)
|
||||
:返回"参数错误";
|
||||
stop
|
||||
endif
|
||||
|
||||
:解析 type(服务编码)、code(权益码)、mac(客户id);
|
||||
|
||||
:基于权益码(code)获取分布式锁;
|
||||
|
||||
if (获取锁成功?) then (否)
|
||||
:返回"请勿重复提交";
|
||||
stop
|
||||
endif
|
||||
|
||||
:defer 释放分布式锁;
|
||||
note right: 使用defer机制确保锁在流程结束时释放
|
||||
|
||||
:查询订单状态(幂等验证);
|
||||
|
||||
if (订单状态?) then (服务已预约 200)
|
||||
:返回预约成功;
|
||||
stop
|
||||
elseif (其他状态) then
|
||||
:返回"服务已预约";
|
||||
elseif (服务已取消 400) then
|
||||
:返回"服务已取消";
|
||||
stop
|
||||
elseif (服务已完成 300) then
|
||||
:返回"服务已生效";
|
||||
stop
|
||||
else (服务未预约 100 或 订单不存在)
|
||||
endif
|
||||
|
||||
:查询数据库验证服务编码(type);
|
||||
|
||||
if (服务编码是否存在?) then (不存在)
|
||||
:返回"暂不支持此服务";
|
||||
stop
|
||||
else (存在)
|
||||
endif
|
||||
|
||||
:请求邮储服务开放平台\n验证权益码有效性;
|
||||
|
||||
if (权益码是否过期?) then (过期)
|
||||
|
|
@ -937,13 +983,15 @@ endif
|
|||
|
||||
| 步骤 | 操作 | 说明 |
|
||||
|-----|------|------|
|
||||
| 1 | AES解密 | 对request进行AES解密,解析出type、code、mac |
|
||||
| 2 | 幂等验证 | 根据订单状态决定后续流程 |
|
||||
| 3 | 验证服务编码 | 查询数据库验证服务编码是否存在 |
|
||||
| 4 | 验证权益码 | 调用邮储平台验证权益码有效性 |
|
||||
| 5 | 创建/更新订单 | 订单状态设为「服务未预约(100)」|
|
||||
| 6 | 发起预约 | 调用邮储平台发起预约 |
|
||||
| 7 | 获取券码 | 调用蓝色兄弟获取券码链接,更新最终状态 |
|
||||
| 1 | 验证服务编码 | 根据入参type查询数据库,获取对应的aes_key和aes_iv |
|
||||
| 2 | AES解密 | 使用数据库查询到的aes_key和aes_iv对request进行解密,解析出type、code、mac |
|
||||
| 3 | 获取分布式锁 | 基于权益码(code)获取锁,防止重复请求 |
|
||||
| 4 | defer释放锁 | 使用defer机制注册锁释放,确保流程结束时自动释放 |
|
||||
| 5 | 幂等验证 | 根据订单状态决定后续流程:已预约→返回成功,已取消→返回"服务已取消",已完成→返回"服务已生效" |
|
||||
| 6 | 验证权益码 | 调用邮储平台验证权益码有效性(前置校验,5s超时) |
|
||||
| 7 | 创建/更新订单 | 订单状态设为「服务未预约(100)」|
|
||||
| 8 | 发起预约 | 调用邮储平台发起预约(5s超时) |
|
||||
| 9 | 获取券码 | 调用蓝色兄弟获取券码链接(幂等,5s超时),更新最终状态 |
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -969,6 +1017,13 @@ if (解密成功?) then (否)
|
|||
stop
|
||||
endif
|
||||
|
||||
:基于权益码(code)获取分布式锁;
|
||||
|
||||
if (获取锁成功?) then (否)
|
||||
:返回"请勿重复提交";
|
||||
stop
|
||||
endif
|
||||
|
||||
:查询本地订单;
|
||||
|
||||
if (订单存在?) then (否)
|
||||
|
|
@ -976,6 +1031,11 @@ if (订单存在?) then (否)
|
|||
stop
|
||||
endif
|
||||
|
||||
if (订单状态=已取消?) then (是)
|
||||
:返回取消成功;
|
||||
stop
|
||||
endif
|
||||
|
||||
if (订单状态=已预约?) then (否)
|
||||
:返回"服务已生效无法取消";
|
||||
stop
|
||||
|
|
@ -1024,11 +1084,13 @@ stop
|
|||
| 步骤 | 操作 | 说明 |
|
||||
|-----|------|------|
|
||||
| 1 | AES解密 | 对request进行AES解密,解析出type、code、mac |
|
||||
| 2 | 本地订单校验 | 查询订单是否存在且状态为已预约 |
|
||||
| 3 | 邮储状态查询 | 调用邮储预约服务状态查询接口,确认可取消 |
|
||||
| 4 | 蓝色兄弟作废 | 调用作废接口,失败时查询券码状态确认 |
|
||||
| 5 | 邮储预约取消 | 调用邮储预约取消接口,确认取消成功 |
|
||||
| 6 | 更新订单状态 | 更新本地订单状态为已取消(400) |
|
||||
| 2 | 获取分布式锁 | 基于权益码(code)获取锁,防止重复请求 |
|
||||
| 3 | 本地订单校验 | 查询订单是否存在,已取消直接返回成功,非已预约返回失败 |
|
||||
| 4 | 邮储状态查询 | 调用邮储预约服务状态查询接口,确认可取消 |
|
||||
| 5 | 蓝色兄弟作废 | 调用作废接口,失败时查询券码状态确认 |
|
||||
| 6 | 邮储预约取消 | 调用邮储预约取消接口,确认取消成功 |
|
||||
| 7 | 更新订单状态 | 更新本地订单状态为已取消(400) |
|
||||
| 8 | 释放锁 | 释放分布式锁 |
|
||||
|
||||
---
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue