Merge remote-tracking branch 'origin/master'

pull/1/head
wqy 1 year ago
commit cce5c23778

@ -10,6 +10,7 @@
## B站讲解视频 ## B站讲解视频
https://www.bilibili.com/video/BV16N4y1d7MM https://www.bilibili.com/video/BV16N4y1d7MM
## 若依视频教程
对若依框架不了解不知道怎么部署、修改密码等操作的请参考https://www.bilibili.com/video/BV1Fi4y1q74p/ 对若依框架不了解不知道怎么部署、修改密码等操作的请参考https://www.bilibili.com/video/BV1Fi4y1q74p/
## 本地运行文档 ## 本地运行文档
https://docs.ichengle.top/mall/run.html https://docs.ichengle.top/mall/run.html
@ -31,9 +32,6 @@ http://mall.ichengle.top
<img src="doc/小程序演示.jpg" width="200px"> <img src="doc/小程序演示.jpg" width="200px">
<img src="doc/h5演示.png" width="200px"> <img src="doc/h5演示.png" width="200px">
### 给大家一个便宜寄快递的福利大件5折小件6折
<img src="doc/express.jpg" width="200px">
## 若依技术专栏 ## 若依技术专栏
- 常见问题https://blog.csdn.net/qq_27575627/category_12336113.html - 常见问题https://blog.csdn.net/qq_27575627/category_12336113.html
- 后端技术https://blog.csdn.net/qq_27575627/category_12331868.html - 后端技术https://blog.csdn.net/qq_27575627/category_12331868.html
@ -42,11 +40,25 @@ http://mall.ichengle.top
## 若依mall功能 ## 若依mall功能
1. 首页: 1. 首页:
![img.png](doc/首页.png)
2. PMS商品管理 2. PMS商品管理
![img.png](doc/商品.png)
![img.png](doc/商品列表.png)
3. UMS会员管理 3. UMS会员管理
会员列表:
![img.png](doc/会员列表.png)
购物车:
![img.png](doc/会员购物车.png)
4. OMS订单管理 4. OMS订单管理
订单列表:
![img.png](doc/订单.png)
售后列表:
![img.png](doc/售后.png)
5. SMS营销管理 5. SMS营销管理
![img.png](doc/优惠券.png)
![img.png](doc/积分.png)
6. CMS内容管理 6. CMS内容管理
![img.png](doc/内容管理.png)
## 交流群/技术支持 ## 交流群/技术支持
| 公众号 | | 公众号 |

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 116 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 92 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 276 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 126 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 149 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 138 KiB

@ -22,7 +22,7 @@
<kaptcha.version>2.3.2</kaptcha.version> <kaptcha.version>2.3.2</kaptcha.version>
<mybatis-spring-boot.version>2.1.4</mybatis-spring-boot.version> <mybatis-spring-boot.version>2.1.4</mybatis-spring-boot.version>
<pagehelper.boot.version>1.3.1</pagehelper.boot.version> <pagehelper.boot.version>1.3.1</pagehelper.boot.version>
<fastjson.version>1.2.78</fastjson.version> <fastjson.version>2.0.43</fastjson.version>
<oshi.version>5.8.0</oshi.version> <oshi.version>5.8.0</oshi.version>
<jna.version>5.8.0</jna.version> <jna.version>5.8.0</jna.version>
<commons.io.version>2.11.0</commons.io.version> <commons.io.version>2.11.0</commons.io.version>

@ -44,15 +44,15 @@ aliyun:
bucketName: 你的bucketName # bucket 名称 bucketName: 你的bucketName # bucket 名称
wechat: wechat:
enabled: false enabled: false
appId: 你的微信服务号信息 appId: 你的微信服务号信息h5的时候需要小程序的时候不需要
secret: 你的微信服务号信息 secret: 你的微信服务号信息h5的时候需要小程序的时候不需要
merchantId: 微信支付商户号 merchantId: 微信支付商户号
privateKeyPath: 微信支付密钥地址相对地址 privateKeyPath: 微信支付密钥地址相对地址
merchantSerialNumber: 微信支付密钥对应的序列号 merchantSerialNumber: 微信支付密钥对应的序列号
apiV3key: 微信支付apiV3key apiV3key: 微信支付apiV3key
notifyUrl: 微信支付回调地址 notifyUrl: 微信支付回调地址
miniProgramAppId: 小程序apppid miniProgramAppId: 小程序apppidh5的时候不需要
miniProgramSecret: miniProgramSecret: 小程序Secreth5的时候不需要
sms: sms:
enabled: true enabled: true
# 阿里云 dysmsapi.aliyuncs.com # 阿里云 dysmsapi.aliyuncs.com

@ -14,12 +14,8 @@ import org.springframework.web.client.RestTemplate;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
import java.security.Timestamp;
import java.time.Instant; import java.time.Instant;
import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
@ -36,6 +32,21 @@ public class CommonTest {
log.info("end {}", System.currentTimeMillis() - start); log.info("end {}", System.currentTimeMillis() - start);
}*/ }*/
@Test
public void testEquals(){
Integer num1 = 100;
Integer num2 = 100;
System.out.println(num1 == num2); // true因为对于 Integer 类型,-128 到 127 之间的值会被缓存
System.out.println(num1.equals(num2)); // true因为它们的值相同
Integer num3 = 200;
Integer num4 = 200;
System.out.println(num3 == num4); // false因为超出了缓存范围会创建新的对象实例
System.out.println(num3.equals(num4)); // true因为它们的值相同
}
@Test @Test
public void test4() throws IOException { public void test4() throws IOException {
String f1 = "D:/build/tt.jpg"; String f1 = "D:/build/tt.jpg";

@ -255,4 +255,10 @@ public class Constants
public static final Integer REFUSE = 2; public static final Integer REFUSE = 2;
public static final Integer GIVING = 3; public static final Integer GIVING = 3;
} }
/**
* json
*/
public static final String[] JSON_WHITELIST_STR = { "org.springframework", "com.ruoyi","com.cyl" };
} }

@ -1,5 +1,6 @@
package com.ruoyi.common.core.redis; package com.ruoyi.common.core.redis;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@ -8,6 +9,7 @@ import java.util.List;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@Service @Service
@Slf4j
public class RedisService { public class RedisService {
@Autowired @Autowired
private RedisCache redisCache; private RedisCache redisCache;
@ -69,7 +71,8 @@ public class RedisService {
public void lock(String key, String jobInfo, Integer lockSecond) throws Exception { public void lock(String key, String jobInfo, Integer lockSecond) throws Exception {
String existJobInfo = redisCache.getCacheObject(key); String existJobInfo = redisCache.getCacheObject(key);
if (StringUtils.isNotEmpty(existJobInfo)) { if (StringUtils.isNotEmpty(existJobInfo)) {
throw new Exception(String.format("获取锁失败: redisKey: %s, existJobInfo: %s", key, existJobInfo)); log.info("获取锁失败: redisKey: {}, existJobInfo: {}", key, existJobInfo);
throw new Exception("请不要反复提交订单!");
} }
redisCache.setCacheObject(key, jobInfo, lockSecond, TimeUnit.SECONDS); redisCache.setCacheObject(key, jobInfo, lockSecond, TimeUnit.SECONDS);
} }

@ -1,14 +1,13 @@
package com.ruoyi.framework.config; package com.ruoyi.framework.config;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature; import com.alibaba.fastjson2.JSONReader;
import com.fasterxml.jackson.databind.JavaType; import com.alibaba.fastjson2.JSONWriter;
import com.fasterxml.jackson.databind.ObjectMapper; import com.alibaba.fastjson2.filter.Filter;
import com.fasterxml.jackson.databind.type.TypeFactory; import com.ruoyi.common.constant.Constants;
import org.springframework.data.redis.serializer.RedisSerializer; import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.SerializationException; import org.springframework.data.redis.serializer.SerializationException;
import com.alibaba.fastjson.parser.ParserConfig;
import org.springframework.util.Assert;
import java.nio.charset.Charset; import java.nio.charset.Charset;
/** /**
@ -18,17 +17,11 @@ import java.nio.charset.Charset;
*/ */
public class FastJson2JsonRedisSerializer<T> implements RedisSerializer<T> public class FastJson2JsonRedisSerializer<T> implements RedisSerializer<T>
{ {
@SuppressWarnings("unused")
private ObjectMapper objectMapper = new ObjectMapper();
public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8"); public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");
private Class<T> clazz; static final Filter AUTO_TYPE_FILTER = JSONReader.autoTypeFilter(Constants.JSON_WHITELIST_STR);
static private Class<T> clazz;
{
ParserConfig.getGlobalInstance().setAutoTypeSupport(true);
}
public FastJson2JsonRedisSerializer(Class<T> clazz) public FastJson2JsonRedisSerializer(Class<T> clazz)
{ {
@ -43,7 +36,7 @@ public class FastJson2JsonRedisSerializer<T> implements RedisSerializer<T>
{ {
return new byte[0]; return new byte[0];
} }
return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET); return JSON.toJSONString(t, JSONWriter.Feature.WriteClassName).getBytes(DEFAULT_CHARSET);
} }
@Override @Override
@ -55,17 +48,6 @@ public class FastJson2JsonRedisSerializer<T> implements RedisSerializer<T>
} }
String str = new String(bytes, DEFAULT_CHARSET); String str = new String(bytes, DEFAULT_CHARSET);
return JSON.parseObject(str, clazz); return JSON.parseObject(str, clazz, AUTO_TYPE_FILTER);
}
public void setObjectMapper(ObjectMapper objectMapper)
{
Assert.notNull(objectMapper, "'objectMapper' must not be null");
this.objectMapper = objectMapper;
}
protected JavaType getJavaType(Class<?> clazz)
{
return TypeFactory.defaultInstance().constructType(clazz);
} }
} }

@ -8,11 +8,6 @@ import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript; import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.data.redis.serializer.StringRedisSerializer; import org.springframework.data.redis.serializer.StringRedisSerializer;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
/** /**
* redis * redis
@ -32,11 +27,6 @@ public class RedisConfig extends CachingConfigurerSupport
FastJson2JsonRedisSerializer serializer = new FastJson2JsonRedisSerializer(Object.class); FastJson2JsonRedisSerializer serializer = new FastJson2JsonRedisSerializer(Object.class);
ObjectMapper mapper = new ObjectMapper();
mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
mapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
serializer.setObjectMapper(mapper);
// 使用StringRedisSerializer来序列化和反序列化redis的key值 // 使用StringRedisSerializer来序列化和反序列化redis的key值
template.setKeySerializer(new StringRedisSerializer()); template.setKeySerializer(new StringRedisSerializer());
template.setValueSerializer(serializer); template.setValueSerializer(serializer);

@ -2,16 +2,8 @@ package com.cyl.h5.controller;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import com.cyl.h5.domain.dto.DeliveryReq; import com.cyl.h5.domain.dto.DeliveryReq;
import com.cyl.h5.domain.form.ApplyRefundForm; import com.cyl.h5.domain.form.*;
import com.cyl.h5.domain.form.OrderCreateForm; import com.cyl.h5.domain.vo.*;
import com.cyl.h5.domain.form.CancelOrderForm;
import com.cyl.h5.domain.form.OrderPayForm;
import com.cyl.h5.domain.vo.OrderPayVO;
import com.cyl.h5.domain.vo.AftersaleRefundInfoVO;
import com.cyl.h5.domain.vo.CountOrderVO;
import com.cyl.h5.domain.vo.H5OrderVO;
import com.cyl.h5.domain.vo.OrderCalcVO;
import com.cyl.h5.domain.form.OrderSubmitForm;
import com.cyl.h5.service.H5OrderService; import com.cyl.h5.service.H5OrderService;
import com.cyl.manager.oms.domain.entity.Aftersale; import com.cyl.manager.oms.domain.entity.Aftersale;
import com.cyl.manager.oms.domain.entity.Order; import com.cyl.manager.oms.domain.entity.Order;
@ -21,7 +13,6 @@ import com.cyl.manager.oms.service.OrderService;
import com.cyl.manager.ums.domain.entity.Member; import com.cyl.manager.ums.domain.entity.Member;
import com.ruoyi.common.constant.Constants; import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.domain.AjaxResult; import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.core.redis.RedisService; import com.ruoyi.common.core.redis.RedisService;
import com.ruoyi.common.enums.AftersaleStatus; import com.ruoyi.common.enums.AftersaleStatus;
import com.ruoyi.common.enums.OrderStatus; import com.ruoyi.common.enums.OrderStatus;
@ -61,7 +52,7 @@ public class H5OrderController {
return ResponseEntity.ok(service.submit(form)); return ResponseEntity.ok(service.submit(form));
}catch (Exception e){ }catch (Exception e){
log.info("创建订单方法异常", e); log.info("创建订单方法异常", e);
throw new RuntimeException("服务繁忙,稍后再试"); throw new RuntimeException(e.getMessage());
}finally { }finally {
try { try {
redisService.unLock(redisKey, redisValue); redisService.unLock(redisKey, redisValue);

@ -8,23 +8,17 @@ import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.cyl.h5.config.SecurityUtil; import com.cyl.h5.config.SecurityUtil;
import com.cyl.h5.domain.form.ApplyRefundForm;
import com.cyl.h5.domain.form.OrderCreateForm;
import com.cyl.h5.domain.dto.OrderProductListDTO; import com.cyl.h5.domain.dto.OrderProductListDTO;
import com.cyl.h5.domain.dto.PayNotifyMessageDTO; import com.cyl.h5.domain.dto.PayNotifyMessageDTO;
import com.cyl.h5.domain.form.CancelOrderForm; import com.cyl.h5.domain.form.*;
import com.cyl.h5.domain.form.OrderPayForm;
import com.cyl.h5.domain.vo.OrderPayVO;
import com.cyl.h5.domain.vo.*; import com.cyl.h5.domain.vo.*;
import com.cyl.h5.domain.form.OrderSubmitForm;
import com.cyl.manager.act.domain.entity.MemberCoupon; import com.cyl.manager.act.domain.entity.MemberCoupon;
import com.cyl.manager.act.mapper.MemberCouponMapper;
import com.cyl.manager.act.service.IntegralHistoryService; import com.cyl.manager.act.service.IntegralHistoryService;
import com.cyl.manager.act.service.MemberCouponService; import com.cyl.manager.act.service.MemberCouponService;
import com.cyl.manager.oms.convert.AftersaleItemConvert; import com.cyl.manager.oms.convert.AftersaleItemConvert;
import com.cyl.manager.oms.convert.OrderItemConvert; import com.cyl.manager.oms.convert.OrderItemConvert;
import com.cyl.manager.oms.mapper.*;
import com.cyl.manager.oms.domain.entity.*; import com.cyl.manager.oms.domain.entity.*;
import com.cyl.manager.oms.mapper.*;
import com.cyl.manager.oms.service.OrderItemService; import com.cyl.manager.oms.service.OrderItemService;
import com.cyl.manager.oms.service.OrderOperateHistoryService; import com.cyl.manager.oms.service.OrderOperateHistoryService;
import com.cyl.manager.pms.domain.entity.Product; import com.cyl.manager.pms.domain.entity.Product;
@ -57,7 +51,6 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.security.core.parameters.P;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils; import org.springframework.util.CollectionUtils;
@ -584,9 +577,27 @@ public class H5OrderService {
QueryWrapper<MemberWechat> memberWechatQw = new QueryWrapper<>(); QueryWrapper<MemberWechat> memberWechatQw = new QueryWrapper<>();
memberWechatQw.eq("member_id", req.getMemberId()); memberWechatQw.eq("member_id", req.getMemberId());
MemberWechat memberWechat = memberWechatMapper.selectOne(memberWechatQw); MemberWechat memberWechat = memberWechatMapper.selectOne(memberWechatQw);
if (memberWechat == null || StrUtil.isBlank(memberWechat.getOpenid())) { if (memberWechat == null) {
throw new RuntimeException("获取用户openId失败"); throw new RuntimeException("获取用户openId失败");
} }
String openId = null;
String appId = null;
//公众号支付流程
if (req.getWechatType() == 1) {
if (StrUtil.isBlank(memberWechat.getOpenid())) {
throw new RuntimeException("获取用户openId失败");
}
openId = memberWechat.getOpenid();
appId = WechatPayData.appId;
}
//小程序支付流程
if (req.getWechatType() == 2) {
if (StrUtil.isBlank(memberWechat.getRoutineOpenid())) {
throw new RuntimeException("获取用户openId失败");
}
openId = memberWechat.getRoutineOpenid();
appId = WechatPayData.miniProgramAppId;
}
QueryWrapper<OrderItem> orderItemQw = new QueryWrapper<>(); QueryWrapper<OrderItem> orderItemQw = new QueryWrapper<>();
orderItemQw.eq("order_id", orderList.get(0).getId()); orderItemQw.eq("order_id", orderList.get(0).getId());
List<OrderItem> orderItemList = orderItemMapper.selectList(orderItemQw); List<OrderItem> orderItemList = orderItemMapper.selectList(orderItemQw);
@ -617,12 +628,6 @@ public class H5OrderService {
} }
//请开启微信支付 wechat.enabled=true //请开启微信支付 wechat.enabled=true
//调用wx的jsapi拿prepayId返回签名等信息 //调用wx的jsapi拿prepayId返回签名等信息
String openId = memberWechat.getOpenid();
String appId = WechatPayData.appId;
if (2 == req.getWechatType()) {
openId = memberWechat.getRoutineOpenid();
appId = WechatPayData.miniProgramAppId;
}
String prepayId = wechatPayService.jsapiPay( String prepayId = wechatPayService.jsapiPay(
String.valueOf(req.getPayId()), String.valueOf(req.getPayId()),
orderDesc, orderDesc,

@ -1,14 +1,14 @@
package com.cyl.manager.act.domain.entity; package com.cyl.manager.act.domain.entity;
import java.math.BigDecimal; import com.baomidou.mybatisplus.annotation.TableName;
import java.time.LocalDateTime;
import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonFormat;
import com.ruoyi.common.annotation.Excel; import com.ruoyi.common.annotation.Excel;
import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiModelProperty;
import lombok.Data; import lombok.Data;
import com.baomidou.mybatisplus.annotation.TableName;
import java.math.BigDecimal;
import java.time.LocalDateTime;
/** /**
* act_coupon_activity * act_coupon_activity
* *
@ -74,9 +74,11 @@ public class CouponActivity {
private LocalDateTime endTime; private LocalDateTime endTime;
@ApiModelProperty("创建时间") @ApiModelProperty("创建时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime createTime; private LocalDateTime createTime;
@ApiModelProperty("修改时间") @ApiModelProperty("修改时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime updateTime; private LocalDateTime updateTime;
} }

@ -1,14 +1,14 @@
package com.cyl.manager.act.domain.entity; package com.cyl.manager.act.domain.entity;
import java.math.BigDecimal; import com.baomidou.mybatisplus.annotation.TableName;
import java.time.LocalDateTime;
import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonFormat;
import com.ruoyi.common.annotation.Excel; import com.ruoyi.common.annotation.Excel;
import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiModelProperty;
import lombok.Data; import lombok.Data;
import com.baomidou.mybatisplus.annotation.TableName;
import java.math.BigDecimal;
import java.time.LocalDateTime;
/** /**
* act_member_coupon * act_member_coupon
* *
@ -82,6 +82,7 @@ public class MemberCoupon {
private LocalDateTime useTime; private LocalDateTime useTime;
@ApiModelProperty("创建时间") @ApiModelProperty("创建时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime createTime; private LocalDateTime createTime;
} }

File diff suppressed because one or more lines are too long
Loading…
Cancel
Save