虚拟电商-话费充值业务(五)充值成功逻辑和网络异常重试逻辑
一、网络异常重试逻辑编写
如果在对接供应商的过程中出现了网络异常,我们需要做一个补偿机制,在任务类型枚举类:TaskTypeEnum中有一种业务状态码是针对远程调用失败的
步骤一:在对接供应商的方法:SupplierServiceImpl类中的recharge方法中,对调用供应商的代码块加上try{}catch{},捕获到异常后,添加重试任务,任务类型枚举为:TaskTypeEnum.REMOTEERROR,业务状态码为:StatusCode.REMOTEERROR
@Override
public void recharge(RechargeRequest rechargeRequest) {//.......................前面的代码省略Result<RechargeResponse> result = null;try {result = doDispatchSupplier(rechargeRequest);} catch (Exception e) {log.error("recharge exception ,{}",e.getMessage());//添加远程调用重试任务rechargeRequest.setErrorCode(StatusCode.REMOTEERROR);supplierTask.addRetryTask(rechargeRequest);return;}if(result !=null){//判断成功还是失败if(result.getCode() == StatusCode.OK){log.info("下单成功,等待充值处理回调!");//特别注意此时订单状态还不能修改为充值成功-----供应商回调之后才能修改为成功updateTrade(rechargeRequest.getOrderNo(),OrderStatusEnum.UNAFFIRM.getCode());//充值处理中等待确认return;}else {//失败就分好几种:余额不足轮转 下单失败重试等if(result.getCode() == StatusCode.BALANCE_NOT_ENOUGH){//模拟余额不足 轮转--到极速/* rechargeRequest.setSupply(Constants.jisuapi);rechargeRequest.setRepeat(0);rechargeRequest.setErrorCode(StatusCode.BALANCE_NOT_ENOUGH);*///将我们余额不足的供应商放入reids 排除集合中cacheService.sAdd(Constants.exclude_supplier,rechargeRequest.getSupply());String nextSupply = nextSupply();System.out.println("轮转到新的供应商为:"+nextSupply);if(nextSupply !=null){rechargeRequest.setSupply(nextSupply);rechargeRequest.setRepeat(0);rechargeRequest.setErrorCode(StatusCode.BALANCE_NOT_ENOUGH);}else {//没有供应商了updateTrade(rechargeRequest.getOrderNo(),OrderStatusEnum.FAIL.getCode());return;}}else if(result.getCode() == StatusCode.ORDER_REQ_FAILED) {//重试逻辑的编写---添加重试任务rechargeRequest.setErrorCode(StatusCode.ORDER_REQ_FAILED);}supplierTask.addRetryTask(rechargeRequest);}}
}
步骤二:在供应商任务接口SupplierTask中添加远程调用异常重试方法:rechargeException
/*** 远程调用异常重试*/public void rechargeException();
步骤三:实现远程调用重试方法
@Override
@Scheduled(fixedRate = 1000)
public void rechargeException() {retry(TaskTypeEnum.REMOTEERROR);
}
步骤四:测试:除了chongba_recharge_mock不启动之外,其他都启动,进行话费充值,模拟远程调用失败场景。
二、供应商话费充值成功逻辑编写
对接调用成功后我们需要将订单状态改为处理中,一段时间后供应商会回调我们系统,我们需要做的就是更改订单状态为充值成功。
步骤一:模拟对接极速成功的情况,在SupplierServiceImpl类中的方法doPostJisu(RechargeRequest rechargeRequest)中,模拟极速返回成功
//map.add("req_status", ""+StatusCode.ERROR);
map.add("req_status", ""+StatusCode.OK);
步骤二:对接下单方法: recharge(RechargeRequest rechargeRequest)逻辑修改,添加对接成功的判断,目前都是失败的情况
判断对接返回的Result结果中的业务状态码,如果是成功的就对接订单修改订单状态为处理中,否则就是目前的一些异常逻辑
@Override
public void recharge(RechargeRequest rechargeRequest) {//.................前面的省略Result<RechargeResponse> result = null;try {result = doDispatchSupplier(rechargeRequest);} catch (Exception e) {log.error("recharge exception ,{}",e.getMessage());//添加远程调用重试任务rechargeRequest.setErrorCode(StatusCode.REMOTEERROR);supplierTask.addRetryTask(rechargeRequest);return;}if(result !=null){//判断成功还是失败if(result.getCode() == StatusCode.OK){log.info("下单成功,等待充值处理回调!");//特别注意此时订单状态还不能修改为充值成功-----供应商回调之后才能修改为成功updateTrade(rechargeRequest.getOrderNo(),OrderStatusEnum.UNAFFIRM.getCode());//充值处理中等待确认return;}else {//失败就分好几种:余额不足轮转 下单失败重试等if(result.getCode() == StatusCode.BALANCE_NOT_ENOUGH){//模拟余额不足 轮转--到极速/* rechargeRequest.setSupply(Constants.jisuapi);rechargeRequest.setRepeat(0);rechargeRequest.setErrorCode(StatusCode.BALANCE_NOT_ENOUGH);*///将我们余额不足的供应商放入reids 排除集合中cacheService.sAdd(Constants.exclude_supplier,rechargeRequest.getSupply());String nextSupply = nextSupply();System.out.println("轮转到新的供应商为:"+nextSupply);if(nextSupply !=null){rechargeRequest.setSupply(nextSupply);rechargeRequest.setRepeat(0);rechargeRequest.setErrorCode(StatusCode.BALANCE_NOT_ENOUGH);}else {//没有供应商了updateTrade(rechargeRequest.getOrderNo(),OrderStatusEnum.FAIL.getCode());return;}}else if(result.getCode() == StatusCode.ORDER_REQ_FAILED) {//重试逻辑的编写---添加重试任务rechargeRequest.setErrorCode(StatusCode.ORDER_REQ_FAILED);}supplierTask.addRetryTask(rechargeRequest);}}
}
步骤三:成功后极速平台会进行一个回调,在chongba_recharge_mock模块中的MockJisuRechargeController中的add方法,回调充吧系统,回调方法在该模块下的BaseController中:rechargeNotify
实际业务中是充吧系统在供应商平台进行配置,回调地址为:
notify-url: http://127.0.0.1:99/order/notify
需要在chongba_recharge_supplier模块的RechargeNotifyController类中补全接收回调的方法,在实际业务中是调用订单的服务处理订单状态。
@Autowired
protected OrderTradeMapper orderTradeMapper;
@RequestMapping(value = "/order/notify")
public String notify(@RequestBody String result) {JSONObject jsonObject = (JSONObject) JSON.parse(result);String orderNo= (String) jsonObject.get("orderNo");int status= Integer.parseInt(jsonObject.get("status").toString());log.info("充值回调成功修改订单{}的状态为{}",orderNo,status);updateTrade(orderNo, status);return "sucess";
}
private void updateTrade(String orderNo, int orderStatus) {//修改订单状态QueryWrapper<OrderTrade> queryWrapper = new QueryWrapper<>();queryWrapper.eq("order_no", orderNo);OrderTrade orderTrade = orderTradeMapper.selectOne(queryWrapper);if(orderTrade!=null) {orderTrade.setOrderStatus(orderStatus);orderTradeMapper.update(orderTrade, queryWrapper);}
}
步骤四:测试
启动所有工程,进行话费充值业务,充值成功后进入订单列表,查看订单状态,因为目前的逻辑是供应商5秒后回调我们系统,所以5秒后刷新一下订单列表页面,查看订单状态已改变。
相关文章:
虚拟电商-话费充值业务(五)充值成功逻辑和网络异常重试逻辑
一、网络异常重试逻辑编写 如果在对接供应商的过程中出现了网络异常,我们需要做一个补偿机制,在任务类型枚举类:TaskTypeEnum中有一种业务状态码是针对远程调用失败的 步骤一:在对接供应商的方法:SupplierServiceImp…...
42.评论日记
怎么看待算命? 我能算到你今晚睡觉前会上一次厕所。 你可以选择相信我算的内容,也可以不信。 你也可以有感觉要上厕所的时候不去拉兜里。 也可以选择相信,早早的拿好纸做准备。 你今晚可能不止上一次,也可能今晚没吃没喝早早…...
MTK-GMS版本国内WIFI受限问题
MTK-GMS版本国内WIFI受限问题解决 文章目录 问题参考资料解决方案方案一 修改配置坑点 方案二 直接修改属性 问题 最近负责ROOM 产品,出现WIFI受限显示,但是网络是通畅的。 GMS 版本,在国外或者国内翻墙网络不会出现WIFI受限显示问题&#…...
C# System.Text.Json 中 JsonConverter 使用详解
总目录 前言 在 C# 开发中,System.Text.Json 是一个高性能的 JSON 处理库,广泛用于序列化和反序列化对象。当默认的序列化行为无法满足需求时,JsonConverter 提供了强大的自定义能力。本文将详细讲解 JsonConverter 的使用方法,帮…...
Leetcode 857 -- 贪心 | 数学
题目描述 雇佣 K 名工人的最低成本 思路 参考官方题解和这里。 代码1(正确) class Solution { public:double mincostToHireWorkers(vector<int>& quality, vector<int>& wage, int k) {int n wage.size();double res 0, totalq …...
基于 SpringBoot 的社区维修平台
收藏关注不迷路!! 🌟文末获取源码数据库🌟 感兴趣的可以先收藏起来,还有大家在毕设选题(免费咨询指导选题),项目以及论文编写等相关问题都可以给我留言咨询,希望帮助更多…...
maven项目添加第三方JAR包
项目开发过程中,不可避免的需要用到一些maven库(公共库、司库等)中没有的冷门jar包依赖,这时,可以将这些第三方JAR包安装到本地maven仓库中,实现项目依赖的一致性。具体步骤如下: 1、下载jar包 …...
C#:接口(interface)
目录 接口的核心是什么? 1. 什么是接口(Interface),为什么要用它? 2. 如何定义和使用接口? 3.什么是引用接口? 如何“引用接口”? “引用接口”的关键点 4. 接口与抽象类的区…...
c#和c++脚本解释器科学运算
说明: 我希望用c#和c写一个脚本解释器,用于科学运算 效果图: step1: c# C:\Users\wangrusheng\RiderProjects\WinFormsApp3\WinFormsApp3\Form1.cs using System; using System.Collections.Generic; using System.Data; using System.Tex…...
2025年嵌入式大厂春招高频面试真题及解析
以下是 2025 年嵌入式大厂春招高频面试真题及解析,结合真题分类和核心知识点整理: 一、C/C++编程基础 1.1 指针与内存 野指针的成因及避免方法(未初始化、释放后未置空) malloc与calloc的区别(后者自动初始化为0) 指针与数组的区别(内存分配方…...
【C++】nlohmann::json 配置加载技术实践:从基础到高级应用
一、nlohmann::json 库概况与核心特性 nlohmann::json 是 C 社区最受欢迎的 JSON 库之一,其设计理念简洁即美,通过单头文件实现完整的 JSON 解析、序列化和操作功能。 1.1 基本特性 nlohmann::json是一个现代C编写的开源JSON库,采用MIT协议…...
ngx_regex_init
定义在 src\core\ngx_regex.c void ngx_regex_init(void) { #if !(NGX_PCRE2)pcre_malloc ngx_regex_malloc;pcre_free ngx_regex_free; #endif } NGX_PCRE21 #if !(NGX_PCRE2) 就为假 条件不成立 ngx_regex_init 函数就成了空实现 NGX_PCRE2 被定义,则表示 Ngin…...
【前端扫盲】postman介绍及使用
Postman 是一款专为 API 开发与测试设计的 全流程协作工具,程序员可通过它高效完成接口调试、自动化测试、文档管理等工作。以下是针对程序员的核心功能介绍和应用场景说明: 一、核心功能亮点 接口请求构建与调试 支持所有 HTTP 方法(GET/POS…...
Lua中os模块函数使用详解
目录 os.clock()os.date([format [, time]])os.difftime(t2, t1)os.execute(command)os.exit([code [, close]])os.getenv(varname)os.remove(filename)os.rename(oldname, newname)os.setlocale(locale [, category])os.time([table])os.tmpname()总结 以下是 Lua 中 os 模块的…...
量子计算与经典计算的拉锯战:一场关于计算未来的辩论
在计算科学领域,一场关于未来的激烈辩论正在上演。2025年3月,D-Wave量子公司的研究人员在《Science》杂志上发表了一项突破性成果,声称他们的量子退火处理器在几分钟内解决了一个经典超级计算机需要数百万年才能完成的复杂现实问题。这一声明…...
MySQL 基础入门
写在前面 关于MySQL的下载安装和其图形化软件Navicat的下载安装,网上已经有了很多的教程,这里就不再赘述了,本文主要是介绍了关于MySQL数据库的基础知识。 MySQL数据库 MySQL数据库基础 MySQL数据库概念 MySQL 数据库: 是一个关系型数据库管理系统 。 支持SQL语…...
GPT模型搭建
GPT模型搭建 1. 章节介绍 本章节聚焦于从0搭建GPT模型,通过事先准备的基础代码,引导学习者逐步构建模型。旨在让程序员、软件架构师和工程师等掌握GPT模型搭建的核心流程,理解其关键组件与技术细节,为实际应用和面试做好准备。 …...
BUUCTF-web刷题篇(8)
17.EasyCalcS 查看源码,发现有段代码有php文件,即calc.php 经过代码审计之后应该要访问calc.php文件,打开后: <?php error_reporting(0); if(!isset($_GET[num])){show_source(__FILE__); }else{$str $_GET[num];$blackli…...
AI SEO内容优化指南:如何打造AI平台青睐的高质量内容
AI SEO内容优化指南:如何打造AI平台青睐的高质量内容 在生成式AI平台(如DeepSeek、Kimi、豆包、腾讯元宝等)主导的搜索新时代,内容优化已成为企业抢占流量入口的核心策略。本文将从内容创作、分发到效果维护全链路,解…...
无需预对齐即可消除批次效应,东京大学团队开发深度学习框架STAIG,揭示肿瘤微环境中的详细基因信息
生物组织是由多种类型细胞构成的复杂网络,这些细胞通过特定的空间配置执行重要功能。近年来,10x Visium、Slide-seq、Stereo-seq 和 STARmap 等空间转录组学 (ST) 技术的进步,使得生物学家们能够在空间结构内绘制基因数据,从而各类…...
B2B2C多用户商城系统:打造新零售电商生态的创新解决方案
在当今数字化时代,电商行业正以前所未有的速度蓬勃发展,而新零售作为电商与传统零售的深度融合,正逐渐成为市场的新宠。为了满足这一变革带来的多元化需求,B2B2C多用户商城系统应运而生,为商家和消费者搭建了一个高效、…...
走向多模态AI之路(二):多模态 AI 如何工作?
目录 前言一、跨模态对齐(Cross-modal Alignment):AI 如何理解不同模态的关系二、多模态融合(Multimodal Fusion):AI 如何整合不同模态的信息三、多模态生成(Multimodal Generation)…...
MCP 实战:实现server端,并在cline调用
本文动手实现一个简单的MCP服务端的编写,并通过MCP Server 实现成绩查询的调用。 一、配置环境 安装mcp和uv, mcp要求python版本 Python >3.10; pip install mcppip install uv 二、编写并启用服务端 # get_score.py from mcp.server.fastmcp import…...
C#游戏开发【第18天】 | 深入理解队列(Queue)与栈(Stack):从基础到任务队列实战
Langchain系列文章目录 01-玩转LangChain:从模型调用到Prompt模板与输出解析的完整指南 02-玩转 LangChain Memory 模块:四种记忆类型详解及应用场景全覆盖 03-全面掌握 LangChain:从核心链条构建到动态任务分配的实战指南 04-玩转 LangChai…...
2.5路径问题专题:LeetCode 64. 最小路径和
动态规划解决最小路径和问题 1. 题目链接 LeetCode 64. 最小路径和 2. 题目描述 给定一个包含非负整数的 m x n 网格 grid,从网格的左上角出发,每次只能向右或向下移动一步,最终到达右下角。要求找到一条路径,使得路径上的数字…...
办公设备管理系统(springboot+ssm+jsp+maven)
基于springboot的办公设备管理系统(springbootssmjspmaven) 系统功能主要有: 欢迎页账号管理 管理员账号管理系统账号添加密码修改 普通管理员管理 用户管理用户添加用户查询 资产类型管理资产信息管理资产档案管理资产报表...
蓝桥杯2024JavaB组的一道真题的解析
文章目录 1.问题描述2.问题描述3.思路分析4.代码分析 1.问题描述 这个是我很久之前写的一个题目,当时研究了这个题目好久,发布了一篇题解,后来很多人点赞,我都没有意识到这个问题的严重性,我甚至都在怀疑自己…...
数据库--SQL
SQL:Structured Query Language,结构化查询语言 SQL是用于管理关系型数据库并对其中的数据进行一系列操作(包括数据插入、查询、修改删除)的一种语言 分类:数据定义语言DDL、数据操纵语言DML、数据控制语言DCL、事务处…...
SQL Server:Log Shipping 说明
目录标题 SQL Server Log Shipping与Oracle归档日志备份对比分析一、SQL Server Log Shipping的日志截断机制二、Oracle归档日志备份对比三、关键配置对比表四、最佳实践建议 如何修改和查看SQL Server默认备份配置防止自动删除?一、查看现有备份配置二、修改备份配…...
Zephyr实时操作系统初步介绍
一、概述 Zephyr是由Linux基金会托管的开源实时操作系统(RTOS),专为资源受限的物联网设备设计。其核心特性包括模块化架构、跨平台兼容性、安全性优先以及丰富的连接协议支持。基于Apache 2.0协议,Zephyr允许商业和非商业用途的自…...
【大模型系列篇】大模型基建工程:基于 FastAPI 自动构建 SSE MCP 服务器 —— 进阶篇
🔥🔥🔥 上期 《大模型基建工程:基于 FastAPI 自动构建 SSE MCP 服务器》中我们使用fastapi-mcp自动挂载fastapi到mcp工具,通过源码分析和实践,我们发现每次sse请求又转到了内部fastapi RESTful api接口&…...
深度学习deeplearn3
# Jupyter Notebook魔法命令,用于在Notebook中内联显示图表 %matplotlib inline# 导入NumPy库,用于高效的数值计算 import numpy as np# 从matplotlib_inline库导入backend_inline模块,用于设置图表显示格式 from matplotlib_inline import b…...
(九)图形管线
一图说明问题 顶点数据->顶点着色器->细分着色器->几何着色器->光栅化->片元着色器->颜色混合 创建图形管线函数放在后面位置 void MyApplication::initVulkan() { createInstance(); createSurface(); pickPhysicalDevice(); createLogicalDevice(); cre…...
7-3 逆序的三位数
程序每次读入一个正3位数,然后输出按位逆序的数字。注意:当输入的数字含有结尾的0时,输出不应带有前导的0。比如输入700,输出应该是7。 输入格式: 每个测试是一个3位的正整数。 输出格式: 输出按位逆序…...
git从历史版本创建新分支或标签
git从某个历史版本创建标签 # 查看历史版本 git log git tag tag-v1.0 780e2a7fc714faf388ba71git从某个分支的指定历史版本中创建新分支 # 查看历史版本 git log # 从历史分支创建标签 git checkout -b new-branch 780e2a7fc714faf388ba71...
HTML 音频(Audio)学习笔记
一、HTML 音频概述 在 HTML 中,音频可以通过多种方式播放,但要确保音频在不同浏览器和设备上都能正常播放,需要掌握一些技巧。HTML5 引入了 <audio> 元素,为音频播放提供了一种标准方法,但在 HTML4 中ÿ…...
五种音频器件综合对比——《器件手册--音频器件》
目录 音频器件 简述 1. 扬声器(Speakers) 2. 麦克风(Microphones) 3. 放大器(Amplifiers) 4. 音频接口(Audio Interfaces) 5. 音频处理器(Audio Processors)…...
数据结构复习(单调栈,单调队列,KMP,manacher,tire,字符串哈希)
单调栈: 介绍: 单调栈用于解决"寻找每个元素左侧/右侧第一个比它小/大的元素"类问题。栈中元素保持单调性,时间复杂度O(n)。 维护一个严格递增栈。对于每个元素a[i],不断弹出栈顶比a[i]大的元素,剩下的栈顶即…...
(学习总结32)Linux 基础 IO
Linux 基础 IO 一、什么是 " 文件 "二、C 文件接口打开文件写文件读文件其它介绍 三、系统文件 I/O传递标志位系统接口写文件系统接口读文件部分系统调用接口介绍打开文件函数 open关闭文件函数 close写入文件函数 write读取文件函数 read 文件描述符 fdfd 0 & 1…...
操作系统(一):概念及主流系统全分析
目录 一.操作系统是什么 二.操作系统的分类 2.1 按应用场景分类 2.2 按实时性分类 2.3 按内核架构分类 2.4 按用户与任务分类 三.主流操作系统比较 四.未来趋势 一.操作系统是什么 操作系统(Operating System, OS)是计算机系统的核心软件&#x…...
三、GPIO
一、GPIO简介 GPIO(General Purpose Input Output)通用输入输出口GPIO引脚电平:0V(低电平)~3.3V(高电平),部分引脚可容忍5V 容忍5V,即部分引脚输入5V的电压,…...
Ceph异地数据同步之-RBD异地同步复制(上)
#作者:闫乾苓 文章目录 前言基于快照的模式(Snapshot-based Mode)工作原理单向同步配置步骤单向同步复制测试双向同步配置步骤双向同步复制测试 前言 Ceph的RBD(RADOS Block Device)支持在两个Ceph集群之间进行异步镜…...
fastapi完全离线环境(无外网)的访问Swagger所做特殊处理
在互联网环境中,只要 启动FastAPI 服务运行在本地机器上,访问 http://localhost:8000/docs(Swagger UI)就可以访问到Swagger界面,但是在完全离线环境(无外网)下如何访问Swagger页面呢࿱…...
在网络中加入预训练的多层感知机(MLP)有什么作用?
在网络中加入预训练的多层感知机(MLP)通常是为了引入先验知识、提升特征表示能力或dropout,具体作用取决于MLP的设计和预训练任务。以下是常见的应用场景和优势: 1. 特征融合与迁移学习:预训练的MLP可以作为特征提取器࿰…...
3.2/Q2,GBD数据库最新文章解读
文章题目:Temporal trends in the burden of vertebral fractures caused by falls in China and globally from 1990 to 2021: a systematic analysis of the Global Burden of Disease Study 2021 DOI:10.1186/s13690-025-01500-y 中文标题:…...
机器学习的一百个概念(9)学习曲线
前言 本文隶属于专栏《机器学习的一百个概念》,该专栏为笔者原创,引用请注明来源,不足和错误之处请在评论区帮忙指出,谢谢! 本专栏目录结构和参考文献请见[《机器学习的一百个概念》 ima 知识库 知识库广场搜索&…...
浅谈Tomcat数据源连接池
目录 为什么需要JDBC连接池 Tomcat JDBC Pool 相关参数 1. 基本配置 2. 连接池大小控制 3. 连接验证与测试 4. 空闲连接回收 5. 连接泄漏与超时 Tomcat JDBC Pool 源码分析(tomcat 8.5.3) DataSourceFactory DataSource ConnectionPool Pool…...
Techub 财报解读:Circle 冲刺 IPO,但收入增长难掩利润困局
作者:Techub 财报解读 撰文:Yangz,Techub News 4 月 1 日,Circle 向美国证券交易委员会(SEC)提交 S-1 文件,计划进行首次公开募股(IPO),股票代码为 CRCL&…...
C++中的链表操作
在C中,链表是一种常见的数据结构,它由一系列节点组成,每个节点包含数据部分和指向下一个节点的指针。C标准库(STL)中提供了std::list和std::forward_list两种链表实现,分别对应双向链表和单向链表。此外&am…...
Vue2 生命周期
文章目录 前言🔄 Vue2 生命周期流程(8个核心钩子)📝 代码中典型用法示例一、您的描述验证二、完整生命周期代码示例三、关键阶段行为说明🔍 常见问题 前言 提示:以下是本篇文章正文内容,下面案…...