This commit is contained in:
LittleBoy 2022-11-26 11:08:28 +08:00
commit 58308c741f
22 changed files with 709 additions and 6 deletions

View File

@ -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>

View File

@ -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));
}
}

View File

@ -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);
}
}

View File

@ -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();
}

View File

@ -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> {
}

View 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;
}

View 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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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();
}

View File

@ -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);
}

View File

@ -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();
}
}

View File

@ -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);
}
}

View File

@ -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;

View File

@ -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);
}
}
}

View File

@ -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 '订单表';

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 6.5 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 18 KiB

View 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 &lt; 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 &lt; current_timestamp
and offline_time > current_timestamp
and status != 0
</select>
</mapper>

View 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>

View File

@ -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);
}
}

View File

@ -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;
}
}