activemq 的延迟队列和幂等性检查
一. 延迟消息队列
1. 在提交支付之后,可以发送一个延迟检查的队列,来主动查询用户在支付宝上的支付状态
在mq的配置/conf/activeMq.xml的broker实例上配置加上schedulerSupport="true",如下图所示

2 延迟检查如果失败,则从新发送新的检查队列,并且要将检查次数减一
// 没有支付,再次发送检查队列
System.out.println("订单号:"+out_trade_no+"尚未支付成功,再次发送检查队列,剩余检查次数:"+count);
if(count>0){
System.out.println("订单号:"+out_trade_no+"检查次数尚未用尽,再次发送检查队列"+count);
count --;
paymentService.sendDelayPaymentCheckQueue(out_trade_no,count);
}else {
System.out.println("订单号:"+out_trade_no+"检查次数耗尽,停止检查,调用关单服务");
}
二. 幂等性检查
调用相同的服务,返回的结果始终一样,叫做幂等性检查.
例子:
第一步,在支付的controller层发起延迟队列
@RequestMapping("/alipay/submit")
@ResponseBody
public String alipay(Model model, HttpServletRequest request,String orderSn){
// 查询对应订单信息
OmsOrder omsOrder = orderService.getOrderBySn(orderSn);
AlipayTradePagePayRequest alipayRequest = new AlipayTradePagePayRequest();//创建API对应的request
alipayRequest.setReturnUrl(AlipayConfig.return_payment_url);
alipayRequest.setNotifyUrl(AlipayConfig.notify_payment_url);//在公共参数中设置回跳和通知地址
Map<String,Object> requestMap= new HashMap<>();
requestMap.put("out_trade_no",orderSn);
requestMap.put("product_code","FAST_INSTANT_TRADE_PAY");
requestMap.put("total_amount",0.01);
requestMap.put("subject",omsOrder.getOmsOrderItems().get(0).getProductName());
alipayRequest.setBizContent(JSON.toJSONString(requestMap));//填充业务参数
String form="";
try {
form = alipayClient.pageExecute(alipayRequest).getBody(); //调用SDK生成表单
} catch (AlipayApiException e) {
e.printStackTrace();
}
// 保存支付数据
PaymentInfo paymentInfo = new PaymentInfo();
paymentInfo.setOrderSn(orderSn);
paymentInfo.setPaymentStatus("0");
paymentInfo.setTotalAmount(omsOrder.getPayAmount());
paymentInfo.setSubject(omsOrder.getOmsOrderItems().get(0).getProductName());
paymentInfo.setOrderId(omsOrder.getId());
paymentService.addPayment(paymentInfo);
System.out.println(form);
// 发送一个检查支付结果的队列(延迟队列)
paymentService.sendDelayPaymentCheckQueue(orderSn,7);// 调用支付宝的支付状态接口程序
return form;
}
@Override
public void sendDelayPaymentCheckQueue(String orderSn,long count) {
// 发送orderSn的延迟检查队列
ConnectionFactory connectionFactory = activeMQUtil.getConnectionFactory(); Connection connection = null;
Session session = null;// 开启消息事务
Queue paymentResultQueue = null; // 队列
MessageProducer producer = null;
try {
connection = connectionFactory.createConnection();
connection.start();
session = connection.createSession(true, Session.SESSION_TRANSACTED);
paymentResultQueue = session.createQueue("PAYMENT_CHECK_QUEUE");
//text文本格式,map键值格式
MapMessage mapMessage=new ActiveMQMapMessage();
mapMessage.setString("out_trade_no",orderSn);
mapMessage.setLong("count",count); //消息延迟消费
mapMessage.setLongProperty(ScheduledMessage.AMQ_SCHEDULED_DELAY,1000*30); producer = session.createProducer(paymentResultQueue);// 消息的生成者
producer.send(mapMessage);
session.commit();
} catch (JMSException e) {
e.printStackTrace();
}finally {
try {
producer.close();
session.close();
connection.close();
} catch (JMSException e) {
e.printStackTrace();
}
} }
@Component
public class PaymentConsumer { @Autowired
PaymentService paymentService; @JmsListener(containerFactory = "jmsQueueListener",destination = "PAYMENT_CHECK_QUEUE")
public void consumePaymentCheckQueue(MapMessage mapMessage) throws JMSException {
String out_trade_no = mapMessage.getString("out_trade_no");
long count = mapMessage.getLong("count"); System.out.println("开始检查支付状态。。。订单号:"+out_trade_no); // 系统支付的幂等性检查
String status = paymentService.checkPayStatus(out_trade_no);
if(status!=null&&!status.equals("已支付")){
// 检查支付状态
Map<String,Object> map = paymentService.checkPayment(out_trade_no); if(map!=null&&(((String)map.get("trade_status")).equals("TRADE_SUCCESS")||((String)map.get("trade_status")).equals("TRADE_FINISHED"))){
// 保存支付信息,发送支付成功队列
System.out.println("订单号:"+out_trade_no+"已经支付成功,继续后续操作");
//
}else{
// 没有支付,再次发送检查队列
System.out.println("订单号:"+out_trade_no+"尚未支付成功,再次发送检查队列,剩余检查次数:"+count);
if(count>0){
System.out.println("订单号:"+out_trade_no+"检查次数尚未用尽,再次发送检查队列"+count);
count --;
paymentService.sendDelayPaymentCheckQueue(out_trade_no,count);
}else {
System.out.println("订单号:"+out_trade_no+"检查次数耗尽,停止检查,调用关单服务"); }
}
} }
}
@Override
public String checkPayStatus(String order_sn) { PaymentInfo paymentInfo = new PaymentInfo();
paymentInfo.setOrderSn(order_sn);
PaymentInfo paymentInfo1 = paymentInfoMapper.selectOne(paymentInfo); return paymentInfo1.getPaymentStatus();
}
@Override
public Map<String, Object> checkPayment(String out_trade_no) { // 调用支付宝,检查支付状态
AlipayTradeQueryRequest request = new AlipayTradeQueryRequest(); Map<String,Object> map = new HashMap<>();
map.put("out_trade_no",out_trade_no);
request.setBizContent(JSON.toJSONString(map));
AlipayTradeQueryResponse response = null;
try {
response = alipayClient.execute(request);
} catch (AlipayApiException e) {
e.printStackTrace();
} if(response.isSuccess()){// isSuccess
System.out.println("调用成功,交易已经创建");
String tradeNo = response.getTradeNo();
String tradeStatus = response.getTradeStatus();
map.put("trade_no",tradeNo);
map.put("trade_status",tradeStatus);
return map;
} else {
System.out.println("调用失败,用户尚未创建交易");//
} return null;
} 以上,就完成了!
activemq 的延迟队列和幂等性检查的更多相关文章
- Dyno-queues 分布式延迟队列 之 生产消费
Dyno-queues 分布式延迟队列 之 生产消费 目录 Dyno-queues 分布式延迟队列 之 生产消费 0x00 摘要 0x01 前情回顾 1.1 设计目标 1.2 选型思路 0x02 产生 ...
- 【RabbitMQ】一文带你搞定RabbitMQ延迟队列
本文口味:鱼香肉丝 预计阅读:10分钟 一.说明 在上一篇中,介绍了RabbitMQ中的死信队列是什么,何时使用以及如何使用RabbitMQ的死信队列.相信通过上一篇的学习,对于死信队列已经有了更 ...
- 【RabbitMQ 实战指南】一 延迟队列
1.什么是延迟队列 延迟队列中存储延迟消息,延迟消息是指当消息被发送到队列中不会立即消费,而是等待一段时间后再消费该消息. 延迟队列很多应用场景,一个典型的应用场景是订单未支付超时取消,用户下单之后3 ...
- PHP基于Redis实现轻量级延迟队列
延迟队列,顾名思义它是一种带有延迟功能的消息队列. 那么,是在什么场景下我才需要这样的队列呢? 一.背景 先看看一下业务场景: 1.会员过期前3天发送召回通知 2.订单支付成功后,5分钟后检测下游环节 ...
- Dyno-queues 分布式延迟队列 之 基本功能
Dyno-queues 分布式延迟队列 之 基本功能 目录 Dyno-queues 分布式延迟队列 之 基本功能 0x00 摘要 0x01 Dyno-queues分布式延迟队列 1.1 设计目标 1. ...
- Dyno-queues 分布式延迟队列 之 辅助功能
Dyno-queues 分布式延迟队列 之 辅助功能 目录 Dyno-queues 分布式延迟队列 之 辅助功能 0x00 摘要 0x01 前文回顾 0x2 Ack机制 2.1 加入Un-ack集合 ...
- 消息队列RabbitMQ(五):死信队列与延迟队列
死信队列 引言 死信队列,英文缩写:DLX .Dead Letter Exchange(死信交换机),其实应该叫做死信交换机才更恰当. 当消息成为Dead message后,可以被重新发送到另一个交换 ...
- C#实现rabbitmq 延迟队列功能
最近在研究rabbitmq,项目中有这样一个场景:在用户要支付订单的时候,如果超过30分钟未支付,会把订单关掉.当然我们可以做一个定时任务,每个一段时间来扫描未支付的订单,如果该订单超过支付时间就关闭 ...
- Java 延迟队列使用
延时队列,第一他是个队列,所以具有对列功能第二就是延时,这就是延时对列,功能也就是将任务放在该延时对列中,只有到了延时时刻才能从该延时对列中获取任务否则获取不到…… 应用场景比较多,比如延时1分钟发短 ...
随机推荐
- maven解决无法从远程仓库获取ojdbc问题
原因 Oracle 的 ojdbc.jar 是收费的,Maven 中央库中实际上没有此资源 解决方法 手动下载相应的jar,然后将其安装到本地仓库.具体操作如下: 1\先去下载相关的jar包或者驱动 ...
- Qt 找不到rc.exe
Qt在window下出现编译错误: LINK : fatal error LNK1158: 无法运行“rc.exe” 解决: 找到rc.exe的放置路径,比如我的在下面: C:\Program Fil ...
- 上手Typescript,让JavaScript适用于大型应用开发
Typescript Typescript是一个基于静态类型的,能编译为JavaScript的JavaScript的超集.也就是说任何JavaScript都可以看成是Typescript,IDE能够更 ...
- [LUOGU3413] SAC#1 - 萌数
题目背景 本题由世界上最蒟蒻最辣鸡最撒比的SOL提供. 寂月城网站是完美信息教室的官网.地址:http://191.101.11.174/mgzd . 题目描述 辣鸡蒟蒻SOL是一个傻逼,他居然觉得数 ...
- opencv::AKAZE检测与匹配
AKAZE局部匹配 AKAZE局部匹配介绍 AOS 构造尺度空间 Hessian矩阵特征点检测 方向指定基于一阶微分图像 描述子生成 与SIFT.SUFR比较 更加稳定 非线性尺度空间 AKAZE速度 ...
- win10下安装openssl
1.下载运行工具:ActivePerl-5.22.1.2201-MSWin32-x64-299574.msi, 安装. 2.执行:perl example.pl,若显示“Hello from Acti ...
- RIDE-工程、测试套件、测试用例三者关系
理论 type的选择: 一般来说:测试项目(directory)-测试套件(file)-测试用例 本质上,“测试项目”和“测试套件”并没有什么区别,但是testcase只能放在file类型的test ...
- [.Net Core 3.0从入门到精通]1.笔记简介及.Net Core3.0介绍
文章目的:.Net Core 3.0学习笔记整理与分享. 面向人群:有一定基础的C#开发人员或学习人员(C#语法一定要掌握). 笔者水平:中级C#开发攻城狮(水平有限,写的不对的地方希望大家指正). ...
- Hadoop 在 windows 7 64位的配置(一)|非cygwin
参照原文 http://blog.csdn.net/supperman_009/article/details/39991809 环境: Hadoop-2.4.1 Windows 7 64位 jd ...
- OptimalSolution(5)--数组和矩阵问题(2)2
一.找到无序数组中最小的k个数 二.在数组中找到出现次数大于N/K的数 三.最长的可整合子数组的长度 四.不重复打印排序数组中相加和为给定值的所有二元组和三元组 五.未排序正数数组中累加和为给定值的最 ...