merge
This commit is contained in:
commit
58308c741f
@ -80,7 +80,7 @@
|
||||
<dependency>
|
||||
<groupId>org.bouncycastle</groupId>
|
||||
<artifactId>bcprov-jdk15on</artifactId>
|
||||
<version>1.57</version>
|
||||
<version>1.69</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.dev33</groupId>
|
||||
|
@ -0,0 +1,28 @@
|
||||
package me.xiaoyan.point.api.controller;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import me.xiaoyan.point.api.pojo.Goods;
|
||||
import me.xiaoyan.point.api.pojo.vo.PageParam;
|
||||
import me.xiaoyan.point.api.service.GoodsService;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("shop/goods")
|
||||
public class ShopGoodsController {
|
||||
@Resource
|
||||
private GoodsService goodsService;
|
||||
|
||||
@GetMapping("query")
|
||||
public Page<Goods> query(
|
||||
int category,
|
||||
int page,
|
||||
int pageSize
|
||||
) {
|
||||
return goodsService.queryByPage(category, Page.of(page, pageSize));
|
||||
}
|
||||
}
|
@ -0,0 +1,76 @@
|
||||
package me.xiaoyan.point.api.controller;
|
||||
|
||||
import cn.dev33.satoken.stp.StpUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import me.xiaoyan.point.api.error.BizException;
|
||||
import me.xiaoyan.point.api.pojo.OrderInfo;
|
||||
import me.xiaoyan.point.api.pojo.vo.CreateOrderData;
|
||||
import me.xiaoyan.point.api.service.GoodsService;
|
||||
import me.xiaoyan.point.api.service.OrderInfoService;
|
||||
import org.springframework.data.redis.core.StringRedisTemplate;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import javax.annotation.Resource;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* 订单表(OrderInfo)表控制层
|
||||
*
|
||||
* @author makejava
|
||||
* @since 2022-11-24 09:32:38
|
||||
*/
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequestMapping("shop/order")
|
||||
public class ShopOrderInfoController {
|
||||
@Resource
|
||||
private OrderInfoService orderInfoService;
|
||||
@Resource
|
||||
private GoodsService goodsService;
|
||||
@Resource
|
||||
private StringRedisTemplate stringRedisTemplate;
|
||||
|
||||
// 是否已经没有库存
|
||||
private ConcurrentHashMap<Integer, Boolean> stockOutMap = new ConcurrentHashMap<>();
|
||||
private static final String CACHE_STOCK_KEY = "goods:stock:";
|
||||
|
||||
private String cacheKey(long gid) {
|
||||
return CACHE_STOCK_KEY + gid;
|
||||
}
|
||||
|
||||
@PostConstruct // 初始化执行一次
|
||||
private void initGoodsStockCache() {
|
||||
//TODO 应该定时更新缓存数据
|
||||
goodsService.queryAllGoodsIdAndStock().forEach(g -> {
|
||||
log.info("缓存 id:{} stock:{} ", g.getId(), g.getStock());
|
||||
// 缓存库存
|
||||
stringRedisTemplate.opsForValue().set(cacheKey(g.getId()), g.getStock().toString());
|
||||
});
|
||||
}
|
||||
|
||||
@PostMapping("create")
|
||||
public OrderInfo create(@Validated @RequestBody CreateOrderData data) {
|
||||
if (data.getGoodsId() <= 0 || data.getBuyCount() <= 0) {
|
||||
throw BizException.create("订单参数不正确");
|
||||
}
|
||||
//1.内存判断
|
||||
if (stockOutMap.get(data.getGoodsId())) {
|
||||
throw BizException.create("库存不足");
|
||||
}
|
||||
//2.缓存(redis)判断
|
||||
long count = stringRedisTemplate.opsForValue().decrement(cacheKey(data.getGoodsId()));
|
||||
if (count < 0) {
|
||||
// 此时库存没有了 , 保存到已买完的对象
|
||||
stockOutMap.put(data.getGoodsId(),true);
|
||||
log.info("stock count ===>" + count);
|
||||
// 对缓存进行库存 + 1
|
||||
stringRedisTemplate.opsForValue().increment(cacheKey(data.getGoodsId())); //
|
||||
throw BizException.create("库存不足");
|
||||
}
|
||||
//3.数据库
|
||||
return orderInfoService.create(StpUtil.getLoginIdAsInt(), data);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,30 @@
|
||||
package me.xiaoyan.point.api.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import me.xiaoyan.point.api.pojo.Goods;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @Entity me.xiaoyan.point.api.pojo.Goods
|
||||
*/
|
||||
@Mapper
|
||||
public interface GoodsMapper extends BaseMapper<Goods> {
|
||||
public Page<Goods> queryByCategory(@Param("category") int category,Page page);
|
||||
|
||||
/**
|
||||
* 扣除商品库存
|
||||
* @param id
|
||||
* @param count
|
||||
* @return
|
||||
*/
|
||||
public int deductCount(@Param("id") int id, @Param("count") int count);
|
||||
public List<Goods> queryAllGoodsIdAndStock();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -0,0 +1,17 @@
|
||||
package me.xiaoyan.point.api.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import me.xiaoyan.point.api.pojo.OrderInfo;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
/**
|
||||
* 订单表(OrderInfo)表数据库访问层
|
||||
*
|
||||
* @author makejava
|
||||
* @since 2022-11-24 09:32:38
|
||||
*/
|
||||
@Mapper
|
||||
public interface OrderInfoMapper extends BaseMapper<OrderInfo> {
|
||||
|
||||
}
|
||||
|
107
api/src/main/java/me/xiaoyan/point/api/pojo/Goods.java
Normal file
107
api/src/main/java/me/xiaoyan/point/api/pojo/Goods.java
Normal file
@ -0,0 +1,107 @@
|
||||
package me.xiaoyan.point.api.pojo;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 商品表
|
||||
* @TableName goods
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
@TableName(value ="goods")
|
||||
public class Goods implements Serializable {
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 商品类别(1:普通 2:精选 3:秒杀 4:抽奖)
|
||||
*/
|
||||
private Integer category;
|
||||
|
||||
/**
|
||||
* 商品类型(1:实物 2:虚拟)
|
||||
*/
|
||||
private Integer type;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private String title;
|
||||
|
||||
/**
|
||||
* 原价
|
||||
*/
|
||||
private Integer originPrice;
|
||||
|
||||
/**
|
||||
* 价格
|
||||
*/
|
||||
private Integer price;
|
||||
|
||||
/**
|
||||
* 库存数量
|
||||
*/
|
||||
private Integer stock;
|
||||
|
||||
/**
|
||||
* 购买最大数量(0表示不限制)
|
||||
*/
|
||||
private Integer limitCount;
|
||||
|
||||
/**
|
||||
* 商品图
|
||||
*/
|
||||
private String cover;
|
||||
|
||||
/**
|
||||
* 描述
|
||||
*/
|
||||
private String description;
|
||||
|
||||
/**
|
||||
* 提示
|
||||
*/
|
||||
private String notice;
|
||||
|
||||
/**
|
||||
* 上架时间
|
||||
*/
|
||||
private Date onlineTime;
|
||||
|
||||
/**
|
||||
* 下架时间
|
||||
*/
|
||||
private Date offlineTime;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private Date createTime;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private Date updateTime;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private Integer status;
|
||||
}
|
50
api/src/main/java/me/xiaoyan/point/api/pojo/OrderInfo.java
Normal file
50
api/src/main/java/me/xiaoyan/point/api/pojo/OrderInfo.java
Normal file
@ -0,0 +1,50 @@
|
||||
package me.xiaoyan.point.api.pojo;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.baomidou.mybatisplus.extension.activerecord.Model;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 订单表(OrderInfo)表实体类
|
||||
*
|
||||
* @author makejava
|
||||
* @since 2022-11-24 09:32:42
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
@TableName(value ="order_info")
|
||||
public class OrderInfo {
|
||||
@TableId
|
||||
//订单编号
|
||||
private String id;
|
||||
//商品编号
|
||||
private Long gid;
|
||||
//价格
|
||||
private Integer price;
|
||||
//购买数量
|
||||
private Integer count;
|
||||
//用户编号
|
||||
private Integer uid;
|
||||
//订单数据
|
||||
private String data;
|
||||
|
||||
private Date createTime;
|
||||
|
||||
private Date updateTime;
|
||||
//订单状态(0:已删除 1:已取消 2:待确认 3:已完成)
|
||||
private Integer status;
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,8 @@
|
||||
package me.xiaoyan.point.api.pojo.dto;
|
||||
|
||||
public class OrderStatus {
|
||||
public static final int DELETE = 0;
|
||||
public static final int CANCEL = 1;
|
||||
public static final int CONFIRM = 2;
|
||||
public static final int DONE = 3;
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
package me.xiaoyan.point.api.pojo.vo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
@Data
|
||||
public class CreateOrderData implements Serializable {
|
||||
private int goodsId;
|
||||
private int buyCount;
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
package me.xiaoyan.point.api.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import me.xiaoyan.point.api.pojo.Goods;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import me.xiaoyan.point.api.pojo.vo.PageParam;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public interface GoodsService extends IService<Goods> {
|
||||
|
||||
Page<Goods> queryByPage(int category, Page page);
|
||||
|
||||
/**
|
||||
* 减库存
|
||||
* @param id
|
||||
* @param count
|
||||
* @return
|
||||
*/
|
||||
boolean deductStock(int id,int count);
|
||||
|
||||
List<Goods> queryAllGoodsIdAndStock();
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
package me.xiaoyan.point.api.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import me.xiaoyan.point.api.pojo.OrderInfo;
|
||||
import me.xiaoyan.point.api.pojo.vo.CreateOrderData;
|
||||
|
||||
/**
|
||||
* 订单表(OrderInfo)表服务接口
|
||||
*
|
||||
* @author makejava
|
||||
* @since 2022-11-24 09:32:44
|
||||
*/
|
||||
public interface OrderInfoService extends IService<OrderInfo> {
|
||||
|
||||
OrderInfo create(int uid, CreateOrderData data);
|
||||
}
|
||||
|
@ -0,0 +1,37 @@
|
||||
package me.xiaoyan.point.api.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import me.xiaoyan.point.api.pojo.Goods;
|
||||
import me.xiaoyan.point.api.service.GoodsService;
|
||||
import me.xiaoyan.point.api.mapper.GoodsMapper;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@Service
|
||||
public class GoodsServiceImpl extends ServiceImpl<GoodsMapper, Goods>
|
||||
implements GoodsService {
|
||||
|
||||
@Override
|
||||
public Page<Goods> queryByPage(int category, Page page) {
|
||||
return this.getBaseMapper().queryByCategory(category, page);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deductStock(int id, int count) {
|
||||
return getBaseMapper().deductCount(id,count) == 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Goods> queryAllGoodsIdAndStock() {
|
||||
return getBaseMapper().queryAllGoodsIdAndStock();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -0,0 +1,84 @@
|
||||
package me.xiaoyan.point.api.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import me.xiaoyan.point.api.error.BizException;
|
||||
import me.xiaoyan.point.api.mapper.OrderInfoMapper;
|
||||
import me.xiaoyan.point.api.pojo.Goods;
|
||||
import me.xiaoyan.point.api.pojo.OrderInfo;
|
||||
import me.xiaoyan.point.api.pojo.UserInfo;
|
||||
import me.xiaoyan.point.api.pojo.dto.OrderStatus;
|
||||
import me.xiaoyan.point.api.pojo.vo.CreateOrderData;
|
||||
import me.xiaoyan.point.api.service.GoodsService;
|
||||
import me.xiaoyan.point.api.service.OrderInfoService;
|
||||
import me.xiaoyan.point.api.service.UserInfoService;
|
||||
import me.xiaoyan.point.api.util.OrderIdGenerator;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 订单表(OrderInfo)表服务实现类
|
||||
*
|
||||
* @author makejava
|
||||
* @since 2022-11-24 09:32:44
|
||||
*/
|
||||
@Service
|
||||
public class OrderInfoServiceImpl extends ServiceImpl<OrderInfoMapper, OrderInfo> implements OrderInfoService {
|
||||
|
||||
@Resource
|
||||
private UserInfoService userInfoService;
|
||||
@Resource
|
||||
private GoodsService goodsService;
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public OrderInfo create(int uid, CreateOrderData data) {
|
||||
// 1.查询用户信息
|
||||
final UserInfo user = userInfoService.getInfoById(uid);
|
||||
// 判断用户信息
|
||||
if (user == null) throw BizException.create("用户信息不存在");
|
||||
if (user.getStatus() != 1) throw BizException.create("用户状态不正确");
|
||||
// 2.查询商品信息
|
||||
final Goods goods = goodsService.getById(data.getGoodsId());
|
||||
if (goods == null) throw BizException.create("兑换的商品不存在");
|
||||
long now = new Date().getTime();
|
||||
if (goods.getOnlineTime().getTime() > now || goods.getOfflineTime().getTime() < now) {
|
||||
throw BizException.create("商品未上架或已下架");
|
||||
}
|
||||
if (goods.getStock() < data.getBuyCount()) throw BizException.create("商品存库不足");
|
||||
// 判断购买数量的限制
|
||||
if(buyHistoryCount(uid,data.getGoodsId()) + data.getBuyCount() > goods.getLimitCount()){
|
||||
throw BizException.create("最多兑换" + goods.getLimitCount() + "件");
|
||||
}
|
||||
// 3.减库存
|
||||
if (!goodsService.deductStock(data.getGoodsId(), data.getBuyCount())) {
|
||||
throw BizException.create("商品库存不足");
|
||||
}
|
||||
// 4.创建订单
|
||||
OrderInfo orderInfo = OrderInfo.builder()
|
||||
.id(OrderIdGenerator.next())
|
||||
.gid((long) data.getGoodsId())
|
||||
.uid(uid)
|
||||
.count(data.getBuyCount())
|
||||
.price(goods.getPrice())
|
||||
.status(OrderStatus.CONFIRM)
|
||||
.build();
|
||||
if (save(orderInfo)) {
|
||||
return orderInfo;
|
||||
}
|
||||
throw BizException.create("创建订单失败");
|
||||
}
|
||||
|
||||
public long buyHistoryCount(int uid, int gid) {
|
||||
QueryWrapper q = new QueryWrapper();
|
||||
q.eq("uid", gid);
|
||||
q.eq("gid", gid);
|
||||
q.ge("status", OrderStatus.CONFIRM); // 状态为2(待确认)和3(已完成)
|
||||
return count(q);
|
||||
}
|
||||
}
|
||||
|
@ -135,6 +135,7 @@ public class UserInfoServiceImpl extends ServiceImpl<UserInfoMapper, UserInfo>
|
||||
final CodeSessionData data = gson.fromJson(content, CodeSessionData.class);
|
||||
if (!StringUtils.hasLength(data.getOpenid()) || !StringUtils.hasLength(data.getSessionKey())
|
||||
|| (data.getErrcode() != null && data.getErrcode() != 0)) {
|
||||
System.out.println(content);
|
||||
throw BizException.create(1101, "换取session失败");
|
||||
}
|
||||
return data;
|
||||
|
@ -0,0 +1,28 @@
|
||||
package me.xiaoyan.point.api.util;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
public class OrderIdGenerator {
|
||||
private static AtomicInteger atomic = new AtomicInteger();
|
||||
private static SimpleDateFormat dateFormat = new SimpleDateFormat("yyMMddHHmmss");
|
||||
private static long prevTime = 0;
|
||||
|
||||
public static String next() {
|
||||
long now = System.currentTimeMillis() / 1000;
|
||||
if (now > prevTime) {
|
||||
prevTime = now;
|
||||
atomic.set(0);
|
||||
}
|
||||
return dateFormat.format(new Date()) + String.format("%05d", atomic.addAndGet(1));
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws InterruptedException {
|
||||
for (int i = 0; i < 1000; i++) {
|
||||
System.out.println(next());
|
||||
Thread.sleep(1);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
create database if not exists points_sys;
|
||||
create database points_sys;
|
||||
use points_sys;
|
||||
create table userinfo
|
||||
(
|
||||
@ -42,4 +42,39 @@ create table sign_record
|
||||
point int(10) not null,
|
||||
ip varchar(50) not null,
|
||||
create_time datetime default current_timestamp
|
||||
) engine = innodb collate = 'utf8mb4_general_ci' comment '打卡记录表';
|
||||
) engine = innodb collate = 'utf8mb4_general_ci' comment '打卡记录表';
|
||||
create_time datetime default current_timestamp
|
||||
) engine = innodb comment '打卡记录表';
|
||||
|
||||
create table goods
|
||||
(
|
||||
id bigint(15) primary key auto_increment,
|
||||
category tinyint(2) null default 1 comment '商品类别(1:普通 2:精选 3:秒杀 4:抽奖)',
|
||||
type tinyint(2) null default 1 comment '商品类型(1:实物 2:虚拟)',
|
||||
title varchar(50) not null,
|
||||
origin_price int(10) unsigned comment '原价' default 0,
|
||||
price int(10) unsigned not null comment '价格',
|
||||
stock int(10) unsigned not null comment '库存数量',
|
||||
limit_count int(10) unsigned null default 1 comment '购买最大数量(0表示不限制)',
|
||||
cover varchar(200) not null comment '商品图',
|
||||
description text not null comment '描述',
|
||||
notice varchar(500) null comment '提示',
|
||||
online_time datetime not null comment '上架时间',
|
||||
offline_time datetime not null comment '下架时间',
|
||||
create_time datetime default current_timestamp,
|
||||
update_time datetime null on update current_timestamp,
|
||||
status tinyint(2) default 1,
|
||||
index ix_title (title)
|
||||
) engine = innodb comment '商品表';
|
||||
|
||||
create table order_info
|
||||
(
|
||||
id varchar(50) not null comment '订单编号',
|
||||
gid bigint(15) not null comment '商品编号',
|
||||
price int(10) not null comment '价格',
|
||||
uid int(10) not null comment '用户编号',
|
||||
data json null comment '订单数据',
|
||||
create_time datetime default current_timestamp,
|
||||
update_time datetime null on update current_timestamp,
|
||||
status tinyint(2) default 1 comment '订单状态(0:已删除 1:待确认 2:已取消 3:已完成)'
|
||||
) comment '订单表';
|
4
api/src/main/resources/docs/process/create_order.svg
Normal file
4
api/src/main/resources/docs/process/create_order.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 6.5 KiB |
1
api/src/main/resources/docs/process/创建订单.svg
Normal file
1
api/src/main/resources/docs/process/创建订单.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 18 KiB |
57
api/src/main/resources/mapper/GoodsMapper.xml
Normal file
57
api/src/main/resources/mapper/GoodsMapper.xml
Normal file
@ -0,0 +1,57 @@
|
||||
<?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="me.xiaoyan.point.api.mapper.GoodsMapper">
|
||||
|
||||
<resultMap id="BaseResultMap" type="me.xiaoyan.point.api.pojo.Goods">
|
||||
<id property="id" column="id" jdbcType="BIGINT"/>
|
||||
<result property="category" column="category" jdbcType="TINYINT"/>
|
||||
<result property="type" column="type" jdbcType="TINYINT"/>
|
||||
<result property="title" column="title" jdbcType="VARCHAR"/>
|
||||
<result property="originPrice" column="origin_price" jdbcType="INTEGER"/>
|
||||
<result property="price" column="price" jdbcType="INTEGER"/>
|
||||
<result property="stock" column="stock" jdbcType="INTEGER"/>
|
||||
<result property="limitCount" column="limit_count" jdbcType="INTEGER"/>
|
||||
<result property="cover" column="cover" jdbcType="VARCHAR"/>
|
||||
<result property="description" column="description" jdbcType="VARCHAR"/>
|
||||
<result property="notice" column="notice" jdbcType="VARCHAR"/>
|
||||
<result property="onlineTime" column="online_time" jdbcType="TIMESTAMP"/>
|
||||
<result property="offlineTime" column="offline_time" jdbcType="TIMESTAMP"/>
|
||||
<result property="createTime" column="create_time" jdbcType="TIMESTAMP"/>
|
||||
<result property="updateTime" column="update_time" jdbcType="TIMESTAMP"/>
|
||||
<result property="status" column="status" jdbcType="TINYINT"/>
|
||||
</resultMap>
|
||||
|
||||
<sql id="Base_Column_List">
|
||||
id,category,type,
|
||||
title,origin_price,price,
|
||||
stock,limit_count,cover,
|
||||
description,notice,online_time,
|
||||
offline_time,create_time,update_time,
|
||||
status
|
||||
</sql>
|
||||
<update id="deductCount">
|
||||
update points_sys.goods
|
||||
set stock=stock - #{count}
|
||||
where id = #{id}
|
||||
and stock >= #{count}
|
||||
</update>
|
||||
<select id="queryByCategory" resultType="me.xiaoyan.point.api.pojo.Goods">
|
||||
select *
|
||||
from points_sys.goods
|
||||
where online_time < current_timestamp
|
||||
and offline_time > current_timestamp
|
||||
and stock > 0
|
||||
and category = #{category}
|
||||
and status != 0
|
||||
</select>
|
||||
<select id="queryAllGoodsIdAndStock" resultType="me.xiaoyan.point.api.pojo.Goods">
|
||||
select id,stock
|
||||
from points_sys.goods
|
||||
where online_time < current_timestamp
|
||||
and offline_time > current_timestamp
|
||||
and status != 0
|
||||
</select>
|
||||
|
||||
</mapper>
|
4
api/src/main/resources/mapper/OrderInfoMapper.xml
Normal file
4
api/src/main/resources/mapper/OrderInfoMapper.xml
Normal file
@ -0,0 +1,4 @@
|
||||
<?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="me.xiaoyan.point.api.mapper.OrderInfoMapper">
|
||||
</mapper>
|
@ -2,12 +2,42 @@ package me.xiaoyan.point.api;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.data.redis.core.StringRedisTemplate;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
@SpringBootTest
|
||||
class ApiApplicationTests {
|
||||
|
||||
@Resource
|
||||
private StringRedisTemplate stringRedisTemplate;
|
||||
@Test
|
||||
void contextLoads() {
|
||||
}
|
||||
void testBuy(long buyCount){
|
||||
long count = stringRedisTemplate.opsForValue().decrement("a",buyCount);
|
||||
System.out.println(count);
|
||||
if(count<0){
|
||||
System.out.println("库存不足");
|
||||
stringRedisTemplate.opsForValue().increment("a",buyCount);
|
||||
return;
|
||||
}
|
||||
if(count == 0){
|
||||
System.out.println("下一次就没有存库了");
|
||||
return;
|
||||
}
|
||||
System.out.println("购买成功");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testRedis(){
|
||||
stringRedisTemplate.opsForValue().set("a","1");
|
||||
System.out.println("----------第1次----------");
|
||||
testBuy(2);
|
||||
System.out.println("----------第2次----------");
|
||||
testBuy(1);
|
||||
System.out.println("----------第3次----------");
|
||||
testBuy(1);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,10 +1,20 @@
|
||||
package me.xiaoyan.point.api;
|
||||
|
||||
import lombok.SneakyThrows;
|
||||
import me.xiaoyan.point.api.pojo.dto.WechatUserInfo;
|
||||
import me.xiaoyan.point.api.util.WechatDecryptDataUtil;
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.spec.IvParameterSpec;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
import java.security.AlgorithmParameters;
|
||||
import java.security.Key;
|
||||
import java.security.Security;
|
||||
|
||||
public class WechatTests {
|
||||
|
||||
|
||||
@ -16,9 +26,11 @@ public class WechatTests {
|
||||
String sessionKey= "091WPNkl23zoha4xbpnl2cev9l4WPNk7";
|
||||
String encryptedData = "3mmRZjsqy3Tpgw78jm7HNB3n6/pb8nX9jS1GgngV4tHGSe+yhKIXy7u7kxXz7nKS5lwNqt+UQCXF3EHHd1PQJowtpYWNhLBjNZcGjEdIi6a5pxntmwmFsjTX+SjPNmq5Th4iKSwSyMjLIByZqJt7N3hB5OyT5YAo54lsJrln8DJoPE1m6kddHcLqnJy+g12QQTP1u3tFvCEostrCpb109Bhe889wAxm55ekPHTQ+JWYCsPy0TsjmyvqZCQZyB+RNtlW/ohCpLe4oCOF0Nz9Id6N+Kj6bXvgDcEMBf3vwMXSnbWHuqJAuLUWwbsspB/2T";
|
||||
String iv = "qfrpHwHjjqPQVlzzxE9D1A==";
|
||||
// sessionKey= "PKX9EeH6y+pzz8qYrga2jQ==";
|
||||
// encryptedData = "SCK0Ik7THl+USkwTRqTQ9BYGe6rWlXosQ8fWA3I3AsFHTCuPnjbsjFooIEZVcS6mq911XeP5BJJBpPU6A1O3aNuC9L7ebXqTMQX83bVBtaDQySvCIlyyq26xhm8AbWWexl5994NJDpKkNml9ilbYia99bF8bXzXvLCksQQkz82EpZTqztzmCrTdFBZOIrJ+lDnl7rSBWJvVVtoagzgSq2Ux59LcJtxCukIUoZ8fz54//Hm4GhrLucO4zPKTi087f77Pd9K9Rz3LLJ79NMQHHQLtZ38Ws79IKoHBZ7xHXbl3O8xPeTBrrWeHbNfNs1CbOyoe0RwXVjs/fMR9451PeLVM5jg4fj3IDyTFjpx5aUzQRaIrSY/BjVFJoxU/viwQC6LsCBOyXl5uV5h+qIPC5suFbmhl5Q56eU07wbOjNxktEIJsIgbrT+GWRZVPba3dUo+6RoZySxCMA16TRKfuTwjXceV3oNueFdTNyw05s9N43OkrLeKcz1dFeNnpA9DHEVngB1J7MY4RkazdKaWzrld1DjxW6+rk01GgtAr3+H88=";
|
||||
// iv = "Ql/m+Ksll5ziCCZj+07J6g==";
|
||||
|
||||
|
||||
sessionKey= "mu1qLLcPuMVfahKOyAdbvQ==";
|
||||
encryptedData = "ld6dARTybGQ2qCBxUBahqsj7SEm5rschi5u+B2c373dwPf/scWDxPcrOevbzyRLIt3e/K5SVHakl992Uq1KsjBSFI+3A6UV3g5mqgoWePt2xwgUwacfpe7XLYw96qTXxGBAoPH306hRkfpo1zjN34tGVhjTj8LIyCH1llbefqlD+deSXvpRgrwhL2GDUAVs++9U3Mz9wSiSImYOUIZuguvSw0SWtqf5SsRDFI9yfGPzB9KubNX8kzRRvV5Aei8pUuhpgeIs9xKlNFVI5syKRQwprYDK9RLO5dq2G0h3CSrNzPfrI62h7vfb/72aUVu+a";
|
||||
iv = "Spu1dAS7ieC/RQ1BYFb0Lw==";
|
||||
|
||||
WechatUserInfo wechatUserInfo = WechatDecryptDataUtil.decryptData(
|
||||
encryptedData,
|
||||
@ -28,4 +40,44 @@ public class WechatTests {
|
||||
);
|
||||
// System.out.println(wechatUserInfo);
|
||||
}
|
||||
//解密手机号
|
||||
private static boolean initialized = false;
|
||||
|
||||
@Test
|
||||
void testAesDecode(){
|
||||
String sessionKey= "mu1qLLcPuMVfahKOyAdbvQ==";
|
||||
String encryptedData = "ld6dARTybGQ2qCBxUBahqsj7SEm5rschi5u+B2c373dwPf/scWDxPcrOevbzyRLIt3e/K5SVHakl992Uq1KsjBSFI+3A6UV3g5mqgoWePt2xwgUwacfpe7XLYw96qTXxGBAoPH306hRkfpo1zjN34tGVhjTj8LIyCH1llbefqlD+deSXvpRgrwhL2GDUAVs++9U3Mz9wSiSImYOUIZuguvSw0SWtqf5SsRDFI9yfGPzB9KubNX8kzRRvV5Aei8pUuhpgeIs9xKlNFVI5syKRQwprYDK9RLO5dq2G0h3CSrNzPfrI62h7vfb/72aUVu+a";
|
||||
String iv = "Spu1dAS7ieC/RQ1BYFb0Lw==";
|
||||
|
||||
byte[] encData = Base64.decodeBase64(encryptedData);
|
||||
byte[] ivData = Base64.decodeBase64(iv);
|
||||
byte[] session = Base64.decodeBase64(sessionKey);
|
||||
String str = decrypt(encData,session,ivData);
|
||||
System.out.println(str);
|
||||
}
|
||||
@SneakyThrows
|
||||
public String decrypt(byte[] encData, byte[] key, byte[] iv) {
|
||||
initialize();
|
||||
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
|
||||
Key sKeySpec = new SecretKeySpec(key, "AES");
|
||||
|
||||
cipher.init(Cipher.DECRYPT_MODE, sKeySpec, generateIV(iv));// 初始化
|
||||
byte[] result = cipher.doFinal(encData);
|
||||
return new String(result, "UTF-8");
|
||||
}
|
||||
|
||||
|
||||
public static AlgorithmParameters generateIV(byte[] iv) throws Exception {
|
||||
AlgorithmParameters params = AlgorithmParameters.getInstance("AES");
|
||||
params.init(new IvParameterSpec(iv));
|
||||
return params;
|
||||
}
|
||||
|
||||
public static void initialize(){
|
||||
if (initialized){
|
||||
return;
|
||||
}
|
||||
Security.addProvider(new BouncyCastleProvider());
|
||||
initialized = true;
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user