当前位置:网站首页>Order timeout cancellation and commodity query by category
Order timeout cancellation and commodity query by category
2022-07-27 18:50:00 【Fantasia of the cat】
1. Order time out cancellation :
Order time out cancellation , It means that the user fails to complete the payment within the specified time after successfully submitting the order , Then close the order and restore the inventory .
There are usually two solutions to realize the overtime cancellation of orders :
- Timing task ( Circular scanning quartz)
- Delay queue (MQ)
Implementation process :

1.2 quartz Timed task framework usage
1.2.1 Add dependency
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
</dependency>1.2.2 Create a scheduled task :
Timing task , Perform the task every specified time
Case study : every other 3 Print every second HelloWorld

1.2.3 Start the scheduled task in the startup class :

2.3 Realize order timeout cancellation
2.3.1 stay service Subproject add spring-boot-starter-quartz rely on
2.3.2 stay api Automatically start class addition @EnableScheduling annotation
2.3.3 stay service Add... To the module job package , add to OrderTimeoutCheckJob class
package com.qfedu.fmmall.service.job;
import com.github.wxpay.sdk.WXPay;
import com.qfedu.fmmall.dao.OrdersMapper;
import com.qfedu.fmmall.entity.Orders;
import com.qfedu.fmmall.service.OrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import tk.mybatis.mapper.entity.Example;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @Description:
* @Author : Jerry
* @create : 2022-07-06 15:36
*/
@Component
public class OrderTimeoutCheckJob {
@Autowired
private OrdersMapper ordersMapper;
@Autowired
private OrderService orderService;
WXPay wxPay = new WXPay(new MyPayConfig());
@Scheduled(cron = "0/5 * * * * ?")
public void checkAndCloseOrder(){
try {
//1. Query over 30min Orders with the status of pending payment
Example example = new Example(Orders.class);
Example.Criteria criteria = example.createCriteria();
criteria.andEqualTo("status","1");
// The current time is pushed forward 30min
Date time = new Date(System.currentTimeMillis() - 30*60*1000);
criteria.andLessThan("createTime",time);
List<Orders> orders = ordersMapper.selectByExample(example);
//2. Access wechat platform interface , Determine the final payment status of the current order
for (int i = 0; i < orders.size(); i++) {
Orders order = orders.get(i);
HashMap<String,String> params = new HashMap<>();
params.put("out_trade_no",order.getOrderId());
Map<String, String> resp = wxPay.orderQuery(params);
System.out.println(resp);
if("SUCCESS".equalsIgnoreCase(resp.get("trade_state"))){
//2.1 If the order has been paid , Then modify the order to " Deliver goods on behalf of / Paid " status2
Orders updateOrder = new Orders();
updateOrder.setOrderId(order.getOrderId());
updateOrder.setStatus("2");
ordersMapper.updateByPrimaryKeySelective(updateOrder);
}else if("NOTPAY".equalsIgnoreCase(resp.get("trade_state"))){
//2.2 If it does not pay Then cancel the order :
// a. Send a request to wechat payment , Close the payment of the current order and continue
Map<String,String> map = wxPay.closeOrder(params);
System.out.println(map);
// b. Close order
orderService.closeOrder(order.getOrderId());
}
}
}catch (Exception e) {
e.printStackTrace();
}
}
}
stay orderService New method in :
SERIALIZABLE Serialization level : All transactions are executed one by one , In this way, there is no interference between transactions .
public void closeOrder(String orderId);
@Override
@Transactional(isolation = Isolation.SERIALIZABLE)
public void closeOrder(String orderId) {
synchronized (this){
// 1. Modify the current order :status=6 closed close_type=1 Overtime unpaid
Orders cancleOrder = new Orders();
cancleOrder.setOrderId(orderId);
cancleOrder.setStatus("6");
cancleOrder.setCloseType(1);
ordersMapper.updateByPrimaryKeySelective(cancleOrder);
// 2. Restore inventory : First, query the product snapshot according to the current order number (skuid buy_count)--> modify product_sku
Example example1 = new Example(OrderItem.class);
Example.Criteria criteria1 = example1.createCriteria();
criteria1.andEqualTo("orderId",orderId);
List<OrderItem> orderItems = orderItemMapper.selectByExample(example1);
// Restore inventory
for (int j = 0; j < orderItems.size(); j++) {
OrderItem orderItem = orderItems.get(j);
// modify
ProductSku productSku = productSkuMapper.selectByPrimaryKey(orderItem.getSkuId());
productSku.setStock( productSku.getStock() + orderItem.getBuyCounts());
productSkuMapper.updateByPrimaryKeySelective(productSku);
}
}
}2. Query products by category :
2.1 Process analysis :

2.2 Interface development :
2.2.1 Query the commodity interface according to the category :
Database analysis sql
Database implementation :
Implementation class :

productMapper New addition :
/**
* According to three-level classification id Page query product information
* @param cid Three levels of classification id
* @param start Starting index
* @param limit Number of query records
* @return
*/
public List<ProductVO> selectProductByCategoryId(@Param("cid") int cid,
@Param("start") int start,
@Param("limit") int limit);
<resultMap id="ProductVOMap2" type="com.qfedu.fmmall.entity.ProductVO" >
<id column="product_id" property="productId" jdbcType="VARCHAR" />
<result column="product_name" property="productName" jdbcType="VARCHAR" />
<result column="category_id" property="categoryId" jdbcType="INTEGER" />
<result column="root_category_id" property="rootCategoryId" jdbcType="INTEGER" />
<result column="sold_num" property="soldNum" jdbcType="INTEGER" />
<result column="product_status" property="productStatus" jdbcType="INTEGER" />
<result column="create_time" property="createTime" jdbcType="TIMESTAMP" />
<result column="update_time" property="updateTime" jdbcType="TIMESTAMP" />
<result column="content" property="content" jdbcType="LONGVARCHAR" />
<!-- According to the goods id Check the package with the lowest price -->
<collection property="skus" column="product_id" select="com.qfedu.fmmall.dao.ProductSkuMapper.selectLowerestPriceByProductId"/>
</resultMap>
<select id="selectProductByCategoryId" resultMap="ProductVOMap2">
select product_id,
product_name,
category_id,
root_category_id,
sold_num,
product_status,
content,
create_time,
update_time
from product
where category_id=#{cid}
limit #{start},#{limit}
</select>Subquery :productSkuMapper:
package com.qfedu.fmmall.dao;
import com.qfedu.fmmall.entity.ProductSku;
import com.qfedu.fmmall.general.GeneralDAO;
import org.springframework.stereotype.Repository;
import java.util.List;
@Repository
public interface ProductSkuMapper extends GeneralDAO<ProductSku> {
/**
* According to the goods id, Query all packages of current goods The lowest price package
* @param productId
* @return
*/
public List<ProductSku> selectLowerestPriceByProductId(String productId);
}<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.qfedu.fmmall.dao.ProductSkuMapper" >
<resultMap id="BaseResultMap" type="com.qfedu.fmmall.entity.ProductSku" >
<!--
WARNING - @mbg.generated
-->
<id column="sku_id" property="skuId" jdbcType="VARCHAR" />
<result column="product_id" property="productId" jdbcType="VARCHAR" />
<result column="sku_name" property="skuName" jdbcType="VARCHAR" />
<result column="sku_img" property="skuImg" jdbcType="VARCHAR" />
<result column="untitled" property="untitled" jdbcType="VARCHAR" />
<result column="original_price" property="originalPrice" jdbcType="INTEGER" />
<result column="sell_price" property="sellPrice" jdbcType="INTEGER" />
<result column="discounts" property="discounts" jdbcType="DECIMAL" />
<result column="stock" property="stock" jdbcType="INTEGER" />
<result column="create_time" property="createTime" jdbcType="TIMESTAMP" />
<result column="update_time" property="updateTime" jdbcType="TIMESTAMP" />
<result column="status" property="status" jdbcType="INTEGER" />
</resultMap>
<select id="selectLowerestPriceByProductId" resultMap="BaseResultMap">
select sku_id,product_id,sku_name,sku_img,untitled,original_price,
sell_price,discounts,stock,create_time,update_time,status
from product_sku
where product_id = #{productId}
ORDER BY sell_price limit 0,1
</select>
</mapper>productService Interface implementation :
public R getProductsByCategoryId(int categoryId,int pageNum,int limit);@Autowired
private ProductMapper productMapper;
@Override
public R getProductsByCategoryId(int categoryId, int pageNum, int limit) {
//1. Query product data
int start = (pageNum - 1)*limit;
List<ProductVO> productVOS = productMapper.selectProductByCategoryId(categoryId, start, limit);
//2. Query the total number of commodity records under the current category
Example example = new Example(Product.class);
Example.Criteria criteria = example.createCriteria();
criteria.andEqualTo("categoryId",categoryId);
int count = productMapper.selectCountByExample(example);
//3. Calculate the total number of pages
int pageCount = count%limit==0? count/limit : count/limit+1;
//4. Encapsulate return data
PageHelper<ProductVO> pageHelper = new PageHelper<>(count,pageCount,productVOS);
return new R(ResStatus.OK,"success",pageHelper);
}2.2.3 By category id Query the brand interface of all goods under the current category
sql:

Database implementation :
productmapper Interface :
public List<String> selectBrandByCategoryId(int cid);Mapping configuration :
<select id="selectBrandByCategoryId" resultSets="java.util.List" resultType="String">
select Distinct brand
from product_params
where product_id in (
select product_id
from product
where category_id=49
)
</select>service Interface :
public R listBrands(int categoryId);@Override
public R listBrands(int categoryId) {
List<String> brands = productMapper.selectBrandByCategoryId(categoryId);
return new R(ResStatus.OK,"success",brands);
}controller Realization :
// Query the commodity interface according to the category
@GetMapping("/listbycid/{cid}")
public R getProductsByCategoryId(@PathVariable("cid") int cid,int pageNum,int pageSize){
return productService.getProductsByCategoryId(cid,pageNum,pageSize);
}
// Query the commodity brand interface according to the category
@GetMapping("/listbrands/{cid}")
public R getBrandsByCategoryId(@PathVariable("cid") int cid){
return productService.listBrands(cid);
}边栏推荐
猜你喜欢

I was forced to optimize the API gateway query interface

Vue uses keep alive to realize page caching

全身多功能按摩仪芯片-DLTAP602SD

Log4j 史诗级漏洞,京东这样的大厂都中招了

js实现简易表单验证与全选功能

2021.8.7 note Servlet

Quick access to website media resources

Knowledge map - Jieba, pyhanlp, smoothnlp tools to realize Chinese word segmentation (part of speech)

MySQL basic statement

MySQL learns the relationship between Day2 Sorting Query / aggregation function / grouping query / paging query / constraint / multiple tables
随机推荐
Quick access to website media resources
Class not found: "the com.parkmanagement.dao.daotest test cannot find the test class
飞机大战碰撞检测
Have you ever stumbled on MySQL's order by
迷你洗衣机触摸芯片-DLT8MA12TS-杰力科创
Uniapp H5 cross domain problem
Must the MySQL query column be consistent with the group by field?
USB充电式暖手宝芯片-DLTAP602SC-杰力科创
MySQL learns the relationship between Day2 Sorting Query / aggregation function / grouping query / paging query / constraint / multiple tables
Wechat applet wechat payment overview
2021.7.30 note index
Use ETL tools for data migration in salesforce project
Conflict between blur event and click event in input box
Log4j epic loopholes, big companies like jd.com have been recruited
Alibaba architects spent 280 hours sorting out 1015 pages of distributed full stack pamphlets to easily start the distributed system
Preliminary introduction to C miscellaneous lecture linked list
RuntimeError: output with shape [1, 256, 256] doesn‘t match the broadcast shape [3, 256, 256]【报错】
2021.8.9 note request
Hbuilder submission code
nacos显示服务注册地址错误