yshop1.8.3,H5注册新增阿里云短信功能,修复移动springsecurity 权限拦截验证问题,解决后台修改价格之后不能重复发起微信支付的问题

This commit is contained in:
hupeng
2020-01-15 18:34:57 +08:00
parent c020c4c190
commit e4e395ff3d
14 changed files with 174 additions and 90 deletions

View File

@ -0,0 +1,2 @@
ALTER TABLE `yxshop`.`yx_store_order`
ADD COLUMN `extend_order_id` varchar(32) NULL COMMENT '额外订单号' AFTER `order_id`

View File

@ -9,6 +9,7 @@ import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import javax.persistence.Column;
import java.math.BigDecimal;
/**
@ -33,6 +34,8 @@ public class YxStoreOrder extends BaseEntity {
@ApiModelProperty(value = "订单号")
private String orderId;
private String extendOrderId;
@ApiModelProperty(value = "用户id")
private Integer uid;

View File

@ -350,6 +350,15 @@ public class YxStoreOrderServiceImpl extends BaseServiceImpl<YxStoreOrderMapper,
storeOrder.setId(orderQueryVo.getId());
storeOrder.setPayPrice(BigDecimal.valueOf(param.getPrice()));
//判断金额是否有变动,生成一个额外订单号去支付
int res = NumberUtil.compare(orderQueryVo.getPayPrice().doubleValue(),param.getPrice());
if(res != 0){
String orderSn = IdUtil.getSnowflake(0,0).nextIdStr();
storeOrder.setExtendOrderId(orderSn);
}
yxStoreOrderMapper.updateById(storeOrder);
//增加状态
@ -1058,6 +1067,9 @@ public class YxStoreOrderServiceImpl extends BaseServiceImpl<YxStoreOrderMapper,
if(ObjectUtil.isNull(wechatUser)) throw new ErrorRequestException("用户错误");
orderRequest.setTradeType("MWEB");
orderRequest.setBody("商品购买");
if(StrUtil.isNotEmpty(orderInfo.getExtendOrderId())){
orderId = orderInfo.getExtendOrderId();
}
orderRequest.setOutTradeNo(orderId);
BigDecimal bigDecimal = new BigDecimal(100);
orderRequest.setTotalFee(bigDecimal.multiply(orderInfo.getPayPrice()).intValue());//元转成分
@ -1106,6 +1118,9 @@ public class YxStoreOrderServiceImpl extends BaseServiceImpl<YxStoreOrderMapper,
orderRequest.setTradeType("JSAPI");
orderRequest.setOpenid(wechatUser.getRoutineOpenid());
orderRequest.setBody("商品购买");
if(StrUtil.isNotEmpty(orderInfo.getExtendOrderId())){
orderId = orderInfo.getExtendOrderId();
}
orderRequest.setOutTradeNo(orderId);
BigDecimal bigDecimal = new BigDecimal(100);
orderRequest.setTotalFee(bigDecimal.multiply(orderInfo.getPayPrice()).intValue());//元转成分
@ -1152,6 +1167,9 @@ public class YxStoreOrderServiceImpl extends BaseServiceImpl<YxStoreOrderMapper,
orderRequest.setTradeType("JSAPI");
orderRequest.setOpenid(wechatUser.getOpenid());
orderRequest.setBody("商品购买");
if(StrUtil.isNotEmpty(orderInfo.getExtendOrderId())){
orderId = orderInfo.getExtendOrderId();
}
orderRequest.setOutTradeNo(orderId);
BigDecimal bigDecimal = new BigDecimal(100);
orderRequest.setTotalFee(bigDecimal.multiply(orderInfo.getPayPrice()).intValue());//元转成分
@ -1407,8 +1425,8 @@ public class YxStoreOrderServiceImpl extends BaseServiceImpl<YxStoreOrderMapper,
//使用MQ延时消息
mqProducer.sendMsg("yshop-topic",storeOrder.getId().toString());
log.info("投递延时订单id [{}]", storeOrder.getId());
//mqProducer.sendMsg("yshop-topic",storeOrder.getId().toString());
//log.info("投递延时订单id [{}]", storeOrder.getId());
return storeOrder;
}
@ -1499,7 +1517,8 @@ public class YxStoreOrderServiceImpl extends BaseServiceImpl<YxStoreOrderMapper,
public YxStoreOrderQueryVo getOrderInfo(String unique,int uid) {
QueryWrapper<YxStoreOrder> wrapper = new QueryWrapper<>();
wrapper.eq("is_del",0).and(
i->i.eq("order_id",unique).or().eq("`unique`",unique));
i->i.eq("order_id",unique).or().eq("`unique`",unique).or()
.eq("extend_order_id",unique));
if(uid > 0) wrapper.eq("uid",uid);
return orderMap.toDto(yxStoreOrderMapper.selectOne(wrapper));

View File

@ -308,8 +308,6 @@ public class StoreOrderController extends BaseController {
if(storeOrder.getPaid() == 1) return ApiResult.fail("该订单已支付");
//todo 砍价
//todo 拼团
String orderId = storeOrder.getOrderId();

View File

@ -29,6 +29,9 @@ public class YxStoreOrderQueryVo implements Serializable {
@ApiModelProperty(value = "订单号")
private String orderId;
private String extendOrderId;
@ApiModelProperty(value = "用户id")
private Integer uid;

View File

@ -18,14 +18,13 @@ import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.filter.CorsFilter;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.*;
/**
* @author hupeng
@ -65,15 +64,33 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
// 搜寻匿名标记 url @AnonymousAccess
Map<RequestMappingInfo, HandlerMethod> handlerMethodMap = applicationContext.getBean(RequestMappingHandlerMapping.class).getHandlerMethods();
Map<RequestMappingInfo, HandlerMethod> handlerMethodMap = applicationContext
.getBean(RequestMappingHandlerMapping.class).getHandlerMethods();
Set<String> anonymousUrls = new HashSet<>();
for (Map.Entry<RequestMappingInfo, HandlerMethod> infoEntry : handlerMethodMap.entrySet()) {
HandlerMethod handlerMethod = infoEntry.getValue();
RequestMappingInfo requestMappingInfo = infoEntry.getKey();
AnonymousAccess anonymousAccess = handlerMethod.getMethodAnnotation(AnonymousAccess.class);
if (null != anonymousAccess) {
Set<String> strings = infoEntry.getKey()
.getPatternsCondition().getPatterns();
if(strings.size() == 1){
String[] arr = strings.toArray((new String[0]));
if(requestMappingInfo.getMethodsCondition().getMethods().contains(RequestMethod.GET)){
String newUrl = arr[0]+"/**";
List<String> list = Arrays.asList(new String[]{newUrl});
Set<String> sSet = new HashSet<>(list);
anonymousUrls.addAll(sSet);
continue;
}
}
anonymousUrls.addAll(infoEntry.getKey().getPatternsCondition().getPatterns());
}
}
httpSecurity
// 禁用 CSRF
.csrf().disable()

View File

@ -13,7 +13,11 @@ import co.yixiang.aop.log.Log;
import co.yixiang.common.api.ApiCode;
import co.yixiang.common.api.ApiResult;
import co.yixiang.exception.ErrorRequestException;
import co.yixiang.modules.notify.NotifyService;
import co.yixiang.modules.notify.NotifyType;
import co.yixiang.modules.notify.SmsResult;
import co.yixiang.modules.security.config.SecurityProperties;
import co.yixiang.modules.security.rest.param.LoginParam;
import co.yixiang.modules.security.rest.param.RegParam;
import co.yixiang.modules.security.rest.param.VerityParam;
import co.yixiang.modules.security.security.TokenProvider;
@ -29,6 +33,9 @@ import co.yixiang.utils.OrderUtil;
import co.yixiang.utils.RedisUtil;
import co.yixiang.utils.RedisUtils;
import co.yixiang.utils.SecurityUtils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.aliyuncs.CommonResponse;
import com.vdurmont.emoji.EmojiParser;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
@ -49,6 +56,7 @@ import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import javax.sound.midi.SoundbankResource;
import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
@ -66,6 +74,9 @@ public class AuthController {
@Value("${single.login:false}")
private Boolean singleLogin;
@Value("${yshop.notify.sms.enable}")
private Boolean enableSms;
private final SecurityProperties properties;
private final RedisUtils redisUtils;
private final UserDetailsService userDetailsService;
@ -77,6 +88,7 @@ public class AuthController {
private final WxMpService wxService;
private final YxWechatUserService wechatUserService;
private final WxMaService wxMaService;
private final NotifyService notifyService;
public AuthController(SecurityProperties properties, RedisUtils redisUtils,
UserDetailsService userDetailsService,
@ -84,7 +96,7 @@ public class AuthController {
AuthenticationManagerBuilder authenticationManagerBuilder,
YxUserService userService, PasswordEncoder passwordEncoder,
WxMpService wxService, YxWechatUserService wechatUserService,
WxMaService wxMaService) {
WxMaService wxMaService,NotifyService notifyService) {
this.properties = properties;
this.redisUtils = redisUtils;
this.userDetailsService = userDetailsService;
@ -96,6 +108,7 @@ public class AuthController {
this.wxService = wxService;
this.wechatUserService = wechatUserService;
this.wxMaService = wxMaService;
this.notifyService = notifyService;
}
@Log("H5用户登录")
@ -265,14 +278,12 @@ public class AuthController {
@AnonymousAccess
@PostMapping("/wxapp/auth")
@ApiOperation(value = "小程序登陆", notes = "小程序登陆")
public ApiResult<Object> login(@RequestParam(value = "code") String code,
@RequestParam(value = "spread") String spread,
@RequestParam(value = "encryptedData") String encryptedData,
@RequestParam(value = "iv") String iv,
public ApiResult<Object> login(@Validated @RequestBody LoginParam loginParam,
HttpServletRequest request) {
if (StringUtils.isBlank(code)) {
return ApiResult.fail("请传code");
}
String code = loginParam.getCode();
String encryptedData = loginParam.getEncryptedData();
String iv = loginParam.getIv();
String spread = loginParam.getSpread();
try {
//读取redis配置
String appId = RedisUtil.get("wxapp_appId");
@ -401,15 +412,36 @@ public class AuthController {
if (param.getType().equals("login") && ObjectUtil.isNull(yxUser)) {
return ApiResult.fail("账号不存在");
}
if (ObjectUtil.isNotNull(redisUtils.get("code_" + param.getPhone()))) {
return ApiResult.fail("10分钟内有效:" + redisUtils.get("code_" + param.getPhone()).toString());
String codeKey = "code_" + param.getPhone();
if (ObjectUtil.isNotNull(redisUtils.get(codeKey))) {
if(!enableSms){
return ApiResult.fail("10分钟内有效:" + redisUtils.get(codeKey).toString());
}
return ApiResult.fail("验证码10分钟内有效,请查看手机短信" );
}
String code = RandomUtil.randomNumbers(6);
redisUtils.set("code_" + param.getPhone(), code, 600L);
if (isTest) {
redisUtils.set(codeKey, code, 600L);
if (!enableSms) {
return ApiResult.fail("测试阶段验证码:" + code);
}
return ApiResult.ok("发送成功");
//发送阿里云短信
SmsResult smsResult = notifyService.notifySmsTemplateSync(param.getPhone(),
NotifyType.CAPTCHA,new String[]{code});
CommonResponse commonResponse = (CommonResponse)smsResult.getResult();
if(smsResult.isSuccessful()){
log.info("详情:{}",commonResponse.getData());
return ApiResult.ok("发送成功,请注意查收");
}else{
JSONObject jsonObject = JSON.parseObject(commonResponse.getData());
log.info("错误详情:{}",commonResponse.getData());
//删除redis存储
redisUtils.del(codeKey);
return ApiResult.ok("发送失败:"+jsonObject.getString("Message"));
}
}
@AnonymousAccess

View File

@ -0,0 +1,22 @@
package co.yixiang.modules.security.rest.param;
import lombok.Data;
import javax.validation.constraints.NotBlank;
/**
* @ClassName LoginParam
* @Author hupeng <610796224@qq.com>
* @Date 2020/02/15
**/
@Data
public class LoginParam {
@NotBlank(message = "code参数缺失")
private String code;
private String spread;
private String encryptedData;
private String iv;
}

View File

@ -112,7 +112,7 @@ public class WechatController extends BaseController {
return WxPayNotifyResponse.success("处理成功!");
}
orderService.paySuccess(orderId,"weixin");
orderService.paySuccess(orderInfo.getOrderId(),"weixin");
return WxPayNotifyResponse.success("处理成功!");
} catch (WxPayException e) {

View File

@ -81,38 +81,5 @@ file:
maxSize: 100
avatarMaxSize: 5
localUrl: http://localhost:8009/api
yshop:
#通知相关配置
notify:
# 短消息模版通知配置
# 短信息用于通知客户例如发货短信通知注意配置格式template-nametemplate-templateId 请参考 NotifyType 枚举值
sms:
enable: false
# 如果是腾讯云短信则设置active的值tencent
# 如果是阿里云短信则设置active的值aliyun
active: tencent
sign: yshop
template:
- name: paySucceed
templateId: 156349
- name: captcha
templateId: 156433
- name: ship
templateId: 158002
- name: refund
templateId: 159447
tencent:
appid: 111111111
appkey: xxxxxxxxxxxxxx
aliyun:
regionId: xxx
accessKeyId: xxx
accessKeySecret: xxx
# 快鸟物流查询配置
express:
enable: true
appId:
appKey:

View File

@ -81,7 +81,7 @@ swagger:
enabled: true
title: yshop商城移动端API
serverUrl: http://localhost:8009
version: 1.7
version: 1.8
# 文件存储路径
file:
@ -92,37 +92,4 @@ file:
avatarMaxSize: 5
localUrl:
yshop:
#通知相关配置
notify:
# 短消息模版通知配置
# 短信息用于通知客户例如发货短信通知注意配置格式template-nametemplate-templateId 请参考 NotifyType 枚举值
sms:
enable: false
# 如果是腾讯云短信则设置active的值tencent
# 如果是阿里云短信则设置active的值aliyun
active: tencent
sign: yshop
template:
- name: paySucceed
templateId: 156349
- name: captcha
templateId: 156433
- name: ship
templateId: 158002
- name: refund
templateId: 159447
tencent:
appid: 111111111
appkey: xxxxxxxxxxxxxx
aliyun:
regionId: xxx
accessKeyId: xxx
accessKeySecret: xxx
# 快鸟物流查询配置
express:
enable: true
appId: 1607734
appKey: 81f43a2e-f504-45c4-9b54-2637d59f8190

View File

@ -74,3 +74,38 @@ logging:
smms:
token: 1oOP3ykFDI0K6ifmtvU7c8Y1eTWZSlyl
yshop:
#通知相关配置
notify:
# 短消息模版通知配置
# 短信息用于通知客户例如发货短信通知注意配置格式template-nametemplate-templateId 请参考 NotifyType 枚举值
sms:
enable: false
# 如果是腾讯云短信则设置active的值tencent
# 如果是阿里云短信则设置active的值aliyun
active: aliyun
sign: yshop
template:
- name: paySucceed
templateId: 156349
- name: captcha
templateId: SMS_182680588
- name: ship
templateId: 158002
- name: refund
templateId: 159447
tencent:
appid: 111111111
appkey: xxxxxxxxxxxxxx
aliyun:
regionId: cn-hangzhou
accessKeyId:
accessKeySecret:
# 快鸟物流查询配置
express:
enable: true
appId: 1607734
appKey: 81f43a2e-f504-45c4-9b54-2637d59f8190

View File

@ -27,6 +27,11 @@ public class YxStoreOrder implements Serializable {
@Column(name = "order_id",nullable = false)
private String orderId;
// 订单号
@Column(name = "extend_order_id",nullable = true)
private String extendOrderId;
// 用户id
@Column(name = "uid",nullable = false)
private Integer uid;

View File

@ -1,5 +1,7 @@
package co.yixiang.modules.shop.rest;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import co.yixiang.aop.log.Log;
@ -10,6 +12,7 @@ import co.yixiang.modules.shop.service.YxExpressService;
import co.yixiang.modules.shop.service.YxStoreOrderService;
import co.yixiang.modules.shop.service.YxStoreOrderStatusService;
import co.yixiang.modules.shop.service.dto.YxExpressDTO;
import co.yixiang.modules.shop.service.dto.YxStoreOrderDTO;
import co.yixiang.modules.shop.service.dto.YxStoreOrderQueryCriteria;
import co.yixiang.modules.wechat.service.YxWechatUserService;
import co.yixiang.modules.wechat.service.dto.YxWechatUserDTO;
@ -236,6 +239,17 @@ public class YxStoreOrderController {
public ResponseEntity editOrder(@RequestBody YxStoreOrder resources){
if(ObjectUtil.isNull(resources.getPayPrice())) throw new BadRequestException("请输入支付金额");
if(resources.getPayPrice().doubleValue() < 0) throw new BadRequestException("金额不能低于0");
YxStoreOrderDTO storeOrder = yxStoreOrderService.findById(resources.getId());
//判断金额是否有变动,生成一个额外订单号去支付
int res = NumberUtil.compare(storeOrder.getPayPrice().doubleValue(),resources.getPayPrice().doubleValue());
if(res != 0){
String orderSn = IdUtil.getSnowflake(0,0).nextIdStr();
resources.setExtendOrderId(orderSn);
}
yxStoreOrderService.update(resources);
YxStoreOrderStatus storeOrderStatus = new YxStoreOrderStatus();