| @@ -102,6 +102,7 @@ public class ShiroConfig { | |||
| filterChainDefinitionMap.put("/wechat/login", "anon"); // 微信第三方登录callback | |||
| filterChainDefinitionMap.put("/wechat/callback", "anon"); // 微信网页登录回调 | |||
| filterChainDefinitionMap.put("/wechat/weChatUserLogin", "anon"); // 微信第三方登录 | |||
| // 验证码 | |||
| filterChainDefinitionMap.put("/captcha.jpg", "anon"); | |||
| // 官网 | |||
| @@ -116,7 +117,7 @@ public class ShiroConfig { | |||
| filterChainDefinitionMap.put("/wxMallApply/sendvalidationcode", "anon"); | |||
| // 补发消息 | |||
| filterChainDefinitionMap.put("/msgrecord/resendMsg", "anon"); | |||
| filterChainDefinitionMap.put("/wxCoupon/updateStokeAndValidDate", "anon"); | |||
| // static files | |||
| filterChainDefinitionMap.put("/css/**", "anon"); | |||
| @@ -66,7 +66,6 @@ public class BaseController { | |||
| public TenantEntity getTenantInfo(){ | |||
| Session session = SecurityUtils.getSubject().getSession(); | |||
| String tenantId = (String)session.getAttribute(UserSession.tenantId); | |||
| TenantEntity tenantEntity = new TenantEntity(){{ | |||
| setTenantId(tenantId); | |||
| }}; | |||
| @@ -99,7 +99,7 @@ public class WxCouponController extends BaseController { | |||
| if (resultData.code != 200) { | |||
| return resultData; | |||
| } | |||
| redisLock.setCouponStock(wxCoupon.getId(), wxCoupon.getInventory()); | |||
| redisLock.setCouponStock(wxCoupon.getId(), wxCoupon.getRemainInventory()); | |||
| //启动投放审批 | |||
| if(wxCoupon.getFlowParams() !=null && wxCoupon.getFlowParams().size()>0) { | |||
| wxCoupon.getFlowParams().put("businessId",wxCoupon.getId()); | |||
| @@ -128,7 +128,7 @@ public class WxCouponController extends BaseController { | |||
| return new ResultData(ResultData.ERROR, "有活动正在上架,请先下架。"); | |||
| } | |||
| } | |||
| redisLock.setCouponStock(wxCoupon.getId(), wxCoupon.getInventory()); | |||
| redisLock.setCouponStock(wxCoupon.getId(), wxCoupon.getRemainInventory()); | |||
| //启动审批流 | |||
| if (wxCoupon.getFlowParams() != null && wxCoupon.getFlowParams().size() > 0) { | |||
| logger.info("------coupon.update().businessType:"+wxCoupon.getFlowParams().get("businessType")); | |||
| @@ -251,9 +251,9 @@ public class WxCouponController extends BaseController { | |||
| updateCoupon.setStockApplyStatus(EnumRentContractAppStatus.APPLYING.getCode()); | |||
| updateCoupon.setUpdateDate(new Date()); | |||
| wxCouponService.update(updateCoupon); | |||
| redisLock.setCouponStock(wxCoupon.getId(), wxCoupon.getInventory()); | |||
| redisLock.setCouponStock(wxCoupon.getId(), wxCoupon.getRemainInventory()); | |||
| } else { | |||
| redisLock.setCouponStock(wxCoupon.getId(), wxCoupon.getInventory()); | |||
| redisLock.setCouponStock(wxCoupon.getId(), wxCoupon.getRemainInventory()); | |||
| return wxCouponService.updateCouponStockAndEndTime(wxCoupon); | |||
| } | |||
| @@ -27,7 +27,7 @@ spring: | |||
| #date-format: yyyy-MM-dd HH:mm:ss | |||
| # REDIS | |||
| redis: | |||
| host: 202.165.179.86 | |||
| host: 101.201.103.81 | |||
| port: 6379 | |||
| password: ENC(xPFDlgd6v8zUhJMbcKc0KmmQiqs9qHtk) | |||
| timeout: 3600 | |||
| @@ -98,7 +98,7 @@ wechat: | |||
| componentToken: "formall2018" | |||
| componentAesKey: "htKq8EjBMPNndfZQK9JiFojFaqFwFpw42VfeWFtx7HN" | |||
| redis: | |||
| host: 202.165.179.86 | |||
| host: 101.201.103.81 | |||
| port: 6379 | |||
| password: ENC(xPFDlgd6v8zUhJMbcKc0KmmQiqs9qHtk) | |||
| timeout: 3600 | |||
| @@ -31,6 +31,7 @@ import com.iformall.service.WxCouponChannelService; | |||
| import com.iformall.service.WxCouponService; | |||
| import com.iformall.service.WxMerchantService; | |||
| import com.iformall.utils.Constant; | |||
| import com.iformall.utils.RedisLock; | |||
| import io.swagger.annotations.Api; | |||
| import io.swagger.annotations.ApiImplicitParam; | |||
| @@ -103,6 +104,7 @@ public class WxCouponController extends BaseController { | |||
| } | |||
| // end of 更新状态 | |||
| updateActivityStatus(wxCouponCVo); | |||
| return new ResultData(wxCouponCVo); | |||
| } | |||
| @@ -18,6 +18,8 @@ import com.iformall.service.WxCouponChannelService; | |||
| import com.iformall.service.WxCouponService; | |||
| import com.iformall.service.WxOrderService; | |||
| import com.iformall.utils.Constant; | |||
| import com.iformall.utils.RedisLock; | |||
| import io.swagger.annotations.Api; | |||
| import io.swagger.annotations.ApiImplicitParam; | |||
| import io.swagger.annotations.ApiImplicitParams; | |||
| @@ -56,6 +58,9 @@ public class WxOrderController extends BaseController { | |||
| @Autowired | |||
| @Qualifier("couponDetailRedisTemplate") | |||
| RedisTemplate<String, WxCouponCVo> cdRedisTemplate; | |||
| @Autowired | |||
| RedisLock redisLock; | |||
| @ApiOperation(value = "下订单", notes = "{\"couponChannelId\":\"String\",\"couponId\":\"String\",\"press\":\"String\",\"orderGroupId\":\"String\",\"formId\":\"String\"}") | |||
| @PostMapping("save") | |||
| @@ -100,6 +105,12 @@ public class WxOrderController extends BaseController { | |||
| return new ResultData(ErrorCode.COUPON_IS_EMPTY); | |||
| } | |||
| //此处判断是否存在绝对保证库存不超卖的缓存,如果没有,则把当前的库存设置为最大值。如果有,则是后台设置的时候保存的,以那个为准。 | |||
| boolean hascache = redisLock.hasCouponStockCache(wxCouponCVo.getCouponId()); | |||
| if (!hascache) { | |||
| redisLock.setCouponStock(wxCouponCVo.getCouponId(), wxCouponCVo.getRemainInventory()); | |||
| } | |||
| resultData = couponUserCheck(user, wxCouponCVo); | |||
| if (resultData != null) return resultData; | |||
| @@ -120,6 +131,7 @@ public class WxOrderController extends BaseController { | |||
| if (coupon.getStatus().equals(EnumCouponStatus.COUPON_STATUS_TAKE_OFFF.getCode())) { | |||
| return new ResultData(ErrorCode.COUPON_IS_TAKE_OFF); | |||
| } | |||
| WxOrder order = wxOrderService.saveOrderForCoupon(user, coupon, orderSaveDto, isPress); | |||
| return new ResultData(order); | |||
| } catch (MallinkException e) { | |||
| @@ -1,32 +1,47 @@ | |||
| package com.iformall.controller; | |||
| import java.util.Map; | |||
| import javax.servlet.http.HttpServletRequest; | |||
| import org.apache.commons.lang3.StringUtils; | |||
| import org.slf4j.Logger; | |||
| import org.slf4j.LoggerFactory; | |||
| import org.springframework.beans.factory.annotation.Autowired; | |||
| import org.springframework.web.bind.annotation.GetMapping; | |||
| import org.springframework.web.bind.annotation.ModelAttribute; | |||
| import org.springframework.web.bind.annotation.PostMapping; | |||
| import org.springframework.web.bind.annotation.RequestBody; | |||
| import org.springframework.web.bind.annotation.RequestMapping; | |||
| import org.springframework.web.bind.annotation.RequestMethod; | |||
| import org.springframework.web.bind.annotation.RestController; | |||
| import com.github.pagehelper.PageInfo; | |||
| import com.iformall.common.ErrorCode; | |||
| import com.iformall.common.IdWorker; | |||
| import com.iformall.common.Result; | |||
| import com.iformall.common.ResultData; | |||
| import com.iformall.domain.po.*; | |||
| import com.iformall.domain.po.WxAppinfo; | |||
| import com.iformall.domain.po.WxCUser; | |||
| import com.iformall.domain.po.WxCUserBasicInfo; | |||
| import com.iformall.domain.po.WxOrder; | |||
| import com.iformall.domain.po.WxPayAccount; | |||
| import com.iformall.domain.po.WxPayOrder; | |||
| import com.iformall.enums.EnumCreditLockedStatus; | |||
| import com.iformall.enums.EnumPayStatus; | |||
| import com.iformall.enums.EnumPayWay; | |||
| import com.iformall.exception.MallinkException; | |||
| import com.iformall.service.WxCUserBasicInfoService; | |||
| import com.iformall.service.WxOrderGroupService; | |||
| import com.iformall.service.WxOrderService; | |||
| import com.iformall.service.WxPayAccountService; | |||
| import com.iformall.service.WxPayOrderService; | |||
| import com.iformall.utils.IPUtil; | |||
| import io.swagger.annotations.Api; | |||
| import io.swagger.annotations.ApiImplicitParam; | |||
| import io.swagger.annotations.ApiImplicitParams; | |||
| import io.swagger.annotations.ApiOperation; | |||
| import org.apache.commons.lang3.StringUtils; | |||
| import org.slf4j.Logger; | |||
| import org.slf4j.LoggerFactory; | |||
| import org.springframework.beans.factory.annotation.Autowired; | |||
| import org.springframework.web.bind.annotation.*; | |||
| import javax.servlet.http.HttpServletRequest; | |||
| import java.util.Map; | |||
| @RestController | |||
| @RequestMapping("/api/pay") | |||
| @@ -45,6 +60,9 @@ public class WxPayOrderController extends BaseController { | |||
| @Autowired | |||
| private WxPayAccountService wxPayAccountService; | |||
| @Autowired | |||
| private WxOrderGroupService orderGroupService; | |||
| //@ApiOperation(value = "发起微信小程序支付订单", notes = "{\"orderId\":\"string\"}") | |||
| @RequestMapping(value = "/create", method = RequestMethod.POST) | |||
| @@ -142,6 +160,10 @@ public class WxPayOrderController extends BaseController { | |||
| } | |||
| if (payOrder.getPayOrderStatus().equals(EnumPayStatus.PAY_STATUS_SUCCESS.getCode())) { | |||
| order = wxOrderService.getById(orderId); | |||
| //如果是拼团,需要处理拼团状态和人数 | |||
| if(order.getOrderGroupId() != null && !order.getOrderGroupId().equals(0L)) { | |||
| orderGroupService.afterPaySuccessUpdate(order); | |||
| } | |||
| return new ResultData(Result.SUCCESS, "支付状态更新成功", order); | |||
| } else{ | |||
| //查询微信订单状态并更新 | |||
| @@ -147,7 +147,7 @@ public class WxPressOrderController extends BaseController { | |||
| return new ResultData(ErrorCode.COUPON_PRESS_HAD_FINISHED); | |||
| } | |||
| long time = System.currentTimeMillis() + RedisLock.TIMEOUT; | |||
| long time = System.currentTimeMillis() + RedisLock.LONG_TIMEOUT; | |||
| String timeStr = String.valueOf(time); | |||
| if (!redisLock.lock(orderIdStr, timeStr)) { | |||
| logger.error("此砍价订单被锁定, orderId: " + orderIdStr); | |||
| @@ -27,7 +27,7 @@ spring: | |||
| #date-format: yyyy-MM-dd HH:mm:ss | |||
| # REDIS | |||
| redis: | |||
| host: 202.165.179.86 | |||
| host: 101.201.103.81 | |||
| port: 6379 | |||
| password: ENC(xPFDlgd6v8zUhJMbcKc0KmmQiqs9qHtk) | |||
| timeout: 3600 | |||
| @@ -97,7 +97,7 @@ wechat: | |||
| componentToken: "formall2018" | |||
| componentAesKey: "htKq8EjBMPNndfZQK9JiFojFaqFwFpw42VfeWFtx7HN" | |||
| redis: | |||
| host: 202.165.179.86 | |||
| host: 101.201.103.81 | |||
| port: 6379 | |||
| password: ENC(xPFDlgd6v8zUhJMbcKc0KmmQiqs9qHtk) | |||
| timeout: 3600 | |||
| @@ -101,9 +101,11 @@ public class MqBaseConsumer { | |||
| UpdateCouponStockMsg msg = (UpdateCouponStockMsg)JsonUtil.readValue(message,UpdateCouponStockMsg.class); | |||
| updateCouponStockMsgService.send(msg); | |||
| } | |||
| baseMsg.setMsgStatus(EnumMsgRecordStatus.CONSUME_SUCC.getCode()); | |||
| wxMsgRecordMapper.updateByBaseMsg(baseMsg); | |||
| //baseMsg.setMsgStatus(EnumMsgRecordStatus.CONSUME_SUCC.getCode()); | |||
| //wxMsgRecordMapper.updateByBaseMsg(baseMsg); | |||
| }catch (Throwable e){ | |||
| log.error("consum received error: ", e); | |||
| /** | |||
| try { | |||
| log.error("consum received error: ", e); | |||
| baseMsg.setStatusMessage(e.getMessage()); | |||
| @@ -129,7 +131,7 @@ public class MqBaseConsumer { | |||
| } | |||
| }catch (Throwable e1){ | |||
| log.error("更新db状态error: ", e1); | |||
| } | |||
| }*/ | |||
| } | |||
| } | |||
| @@ -41,35 +41,39 @@ public class AliyunRocketMqConsumer extends MqBaseConsumer { | |||
| @Value("${spring.aliyunRocketmq.namesrvAddr}") | |||
| private String namesrvAddr; | |||
| private static Consumer consumer = null; | |||
| @PostConstruct | |||
| public void init() { | |||
| Properties properties = new Properties(); | |||
| // 您在控制台创建的 Group ID | |||
| properties.put(PropertyKeyConst.GROUP_ID, groupId); | |||
| // AccessKey 阿里云身份验证,在阿里云服务器管理控制台创建 | |||
| properties.put(PropertyKeyConst.AccessKey, accessKeyId); | |||
| // SecretKey 阿里云身份验证,在阿里云服务器管理控制台创建 | |||
| properties.put(PropertyKeyConst.SecretKey, accessKeySecret); | |||
| // 设置 TCP 接入域名,到控制台的实例基本信息中查看 | |||
| properties.put(PropertyKeyConst.NAMESRV_ADDR,namesrvAddr); | |||
| // 集群订阅方式(默认) | |||
| // properties.put(PropertyKeyConst.MessageModel, PropertyValueConst.CLUSTERING); | |||
| // 广播订阅方式 | |||
| // properties.put(PropertyKeyConst.MessageModel, PropertyValueConst.BROADCASTING); | |||
| consumer = ONSFactory.createConsumer(properties); | |||
| consumer.subscribe(EnumMsgMqTopic.DEFAULT.getCode(), "*", new MessageListener() { //订阅多个 Tag | |||
| public Action consume(Message message, ConsumeContext context) { | |||
| System.out.println("Receive: " + message); | |||
| doMessage(new String(message.getBody())); | |||
| return Action.CommitMessage; | |||
| } | |||
| }); | |||
| consumer.start(); | |||
| log.info(" aliyunrocketMq consumer start success! "+JSON.toJSONString(consumer)); | |||
| for (EnumMsgMqTopic topic: EnumMsgMqTopic.values()) { | |||
| Properties properties = new Properties(); | |||
| // 您在控制台创建的 Group ID | |||
| properties.put(PropertyKeyConst.GROUP_ID, topic.getGroupId()); | |||
| // AccessKey 阿里云身份验证,在阿里云服务器管理控制台创建 | |||
| properties.put(PropertyKeyConst.AccessKey, accessKeyId); | |||
| // SecretKey 阿里云身份验证,在阿里云服务器管理控制台创建 | |||
| properties.put(PropertyKeyConst.SecretKey, accessKeySecret); | |||
| // 设置 TCP 接入域名,到控制台的实例基本信息中查看 | |||
| properties.put(PropertyKeyConst.NAMESRV_ADDR,namesrvAddr); | |||
| // 集群订阅方式(默认) | |||
| // properties.put(PropertyKeyConst.MessageModel, PropertyValueConst.CLUSTERING); | |||
| // 广播订阅方式 | |||
| // properties.put(PropertyKeyConst.MessageModel, PropertyValueConst.BROADCASTING); | |||
| Consumer consumer = ONSFactory.createConsumer(properties); | |||
| consumer.subscribe(topic.getCode(), "*", new MessageListener() { //订阅多个 Tag | |||
| public Action consume(Message message, ConsumeContext context) { | |||
| try { | |||
| System.out.println("Receive: " + message); | |||
| doMessage(new String(message.getBody())); | |||
| return Action.CommitMessage; | |||
| }catch(Exception e) { | |||
| log.error("AliyunRocketMqConsumer error:",e); | |||
| return Action.ReconsumeLater; | |||
| } | |||
| } | |||
| }); | |||
| consumer.start(); | |||
| log.info(" aliyunrocketMq consumer start success! "+JSON.toJSONString(consumer)); | |||
| } | |||
| } | |||
| } | |||
| @@ -28,7 +28,7 @@ spring: | |||
| # REDIS | |||
| redis: | |||
| host: 202.165.179.86 | |||
| host: 101.201.103.81 | |||
| port: 6379 | |||
| password: ENC(xPFDlgd6v8zUhJMbcKc0KmmQiqs9qHtk) | |||
| timeout: 3600 | |||
| @@ -91,7 +91,7 @@ wechat: | |||
| componentToken: "formall2018" | |||
| componentAesKey: "htKq8EjBMPNndfZQK9JiFojFaqFwFpw42VfeWFtx7HN" | |||
| redis: | |||
| host: 202.165.179.86 | |||
| host: 101.201.103.81 | |||
| port: 6379 | |||
| password: ENC(xPFDlgd6v8zUhJMbcKc0KmmQiqs9qHtk) | |||
| timeout: 3600 | |||
| @@ -26,7 +26,7 @@ spring: | |||
| #date-format: yyyy-MM-dd HH:mm:ss | |||
| # REDIS | |||
| redis: | |||
| host: 202.165.179.86 | |||
| host: 101.201.103.81 | |||
| port: 6379 | |||
| password: ENC(xPFDlgd6v8zUhJMbcKc0KmmQiqs9qHtk) | |||
| timeout: 3600 | |||
| @@ -95,7 +95,7 @@ wechat: | |||
| componentToken: "formall2018" | |||
| componentAesKey: "htKq8EjBMPNndfZQK9JiFojFaqFwFpw42VfeWFtx7HN" | |||
| redis: | |||
| host: 202.165.179.86 | |||
| host: 101.201.103.81 | |||
| port: 6379 | |||
| password: ENC(xPFDlgd6v8zUhJMbcKc0KmmQiqs9qHtk) | |||
| timeout: 3600 | |||
| @@ -7,6 +7,8 @@ import org.springframework.beans.factory.annotation.Value; | |||
| import org.springframework.boot.SpringApplication; | |||
| import org.springframework.boot.autoconfigure.SpringBootApplication; | |||
| import org.springframework.context.annotation.Bean; | |||
| import org.springframework.context.annotation.EnableAspectJAutoProxy; | |||
| import springfox.documentation.swagger2.annotations.EnableSwagger2; | |||
| /** | |||
| @@ -18,6 +20,7 @@ import springfox.documentation.swagger2.annotations.EnableSwagger2; | |||
| @EnableSwagger2 | |||
| @EnableRocketMQ | |||
| @EnableEncryptableProperties | |||
| @EnableAspectJAutoProxy(exposeProxy = true) | |||
| public class ScheduleApplication { | |||
| @Value("${fm.exception}") | |||
| @@ -28,7 +28,7 @@ spring: | |||
| # REDIS | |||
| redis: | |||
| host: 202.165.179.86 | |||
| host: 101.201.103.81 | |||
| port: 6379 | |||
| password: ENC(xPFDlgd6v8zUhJMbcKc0KmmQiqs9qHtk) | |||
| timeout: 3600 | |||
| @@ -91,7 +91,7 @@ wechat: | |||
| componentToken: "formall2018" | |||
| componentAesKey: "htKq8EjBMPNndfZQK9JiFojFaqFwFpw42VfeWFtx7HN" | |||
| redis: | |||
| host: 202.165.179.86 | |||
| host: 101.201.103.81 | |||
| port: 6379 | |||
| password: ENC(xPFDlgd6v8zUhJMbcKc0KmmQiqs9qHtk) | |||
| timeout: 3600 | |||
| @@ -16,6 +16,8 @@ import java.util.Date; | |||
| @EqualsAndHashCode(callSuper = true) | |||
| public class WxCardInfo extends TenantEntity { | |||
| private static final long serialVersionUID = 2974374593127477999L; | |||
| @Excel(name = "卡号", width = 20, orderNum = "1") | |||
| @io.swagger.annotations.ApiModelProperty(value="主键ID-与coupon_order_id一致",name="id") | |||
| protected Long id; | |||
| @@ -4,8 +4,8 @@ package com.iformall.enums; | |||
| * Created by luozukai | |||
| */ | |||
| public enum EnumMsgMqTopic { | |||
| DEFAULT("topic-1", "默认"), | |||
| STOCK("stock","库存"), | |||
| DEFAULT("topic-1","GID_P_1", "默认"), | |||
| STOCK("stock","GID_P_2","库存"), | |||
| ; | |||
| public static EnumMsgMqTopic getEnum(String code) { | |||
| @@ -19,10 +19,12 @@ public enum EnumMsgMqTopic { | |||
| private String code; | |||
| private String message; | |||
| private String groupId; | |||
| EnumMsgMqTopic(String code, String message) { | |||
| EnumMsgMqTopic(String code, String groupId,String message) { | |||
| this.code = code; | |||
| this.message = message; | |||
| this.groupId = groupId; | |||
| } | |||
| public String getCode() { | |||
| @@ -32,4 +34,12 @@ public enum EnumMsgMqTopic { | |||
| public String getMessage() { | |||
| return message; | |||
| } | |||
| public String getGroupId() { | |||
| return groupId; | |||
| } | |||
| public void setGroupId(String groupId) { | |||
| this.groupId = groupId; | |||
| } | |||
| } | |||
| @@ -11,5 +11,7 @@ public interface WxCardInfoMapper extends CommonMapper<WxCardInfo, Long> { | |||
| List<WxCardVo> findVoList(WxCardVo wxCardVo); | |||
| void updateTransferStatusByCouponId(Long couponId); | |||
| List<WxCardInfo> findList(WxCardInfo wxCardInfo); | |||
| } | |||
| @@ -1,6 +1,8 @@ | |||
| package com.iformall.mq.impl; | |||
| import java.util.Date; | |||
| import java.util.HashMap; | |||
| import java.util.Map; | |||
| import java.util.Properties; | |||
| import javax.annotation.PostConstruct; | |||
| @@ -18,6 +20,7 @@ import com.aliyun.openservices.ons.api.Producer; | |||
| import com.aliyun.openservices.ons.api.PropertyKeyConst; | |||
| import com.aliyun.openservices.ons.api.SendResult; | |||
| import com.iformall.domain.po.msg.BaseMsg; | |||
| import com.iformall.enums.EnumMsgMqTopic; | |||
| import com.iformall.mq.MQConfig; | |||
| import com.iformall.mq.MqBaseProducer; | |||
| import com.iformall.utils.JsonUtil; | |||
| @@ -52,28 +55,37 @@ public class AliyunRocketMqMessageProducer implements MqBaseProducer { | |||
| //@Autowired | |||
| //private WxMsgRecordService wxMsgRecordService; | |||
| private static Producer producer = null; | |||
| private static Map<String,Producer> producerMap = null; | |||
| @PostConstruct | |||
| public void init() { | |||
| Properties properties = new Properties(); | |||
| properties.setProperty(PropertyKeyConst.GROUP_ID, groupId); | |||
| // AccessKey 阿里云身份验证,在阿里云服务器管理控制台创建 | |||
| properties.put(PropertyKeyConst.AccessKey,accessKeyId); | |||
| // SecretKey 阿里云身份验证,在阿里云服务器管理控制台创建 | |||
| properties.put(PropertyKeyConst.SecretKey, accessKeySecret); | |||
| //设置发送超时时间,单位毫秒 | |||
| properties.setProperty(PropertyKeyConst.SendMsgTimeoutMillis, "3000"); | |||
| // 设置 TCP 接入域名,到控制台的实例基本信息中查看 | |||
| properties.put(PropertyKeyConst.NAMESRV_ADDR,namesrvAddr); | |||
| producer = ONSFactory.createProducer(properties); | |||
| // 在发送消息前,必须调用 start 方法来启动 Producer,只需调用一次即可 | |||
| producer.start(); | |||
| log.info("aliyunrocketmq producer info :"+JSON.toJSONString(producer)); | |||
| producerMap = new HashMap<String,Producer>(); | |||
| for (EnumMsgMqTopic topic: EnumMsgMqTopic.values()) { | |||
| Properties properties = new Properties(); | |||
| properties.setProperty(PropertyKeyConst.GROUP_ID, topic.getGroupId()); | |||
| // AccessKey 阿里云身份验证,在阿里云服务器管理控制台创建 | |||
| properties.put(PropertyKeyConst.AccessKey,accessKeyId); | |||
| // SecretKey 阿里云身份验证,在阿里云服务器管理控制台创建 | |||
| properties.put(PropertyKeyConst.SecretKey, accessKeySecret); | |||
| //设置发送超时时间,单位毫秒 | |||
| properties.setProperty(PropertyKeyConst.SendMsgTimeoutMillis, "3000"); | |||
| // 设置 TCP 接入域名,到控制台的实例基本信息中查看 | |||
| properties.put(PropertyKeyConst.NAMESRV_ADDR,namesrvAddr); | |||
| Producer producer = ONSFactory.createProducer(properties); | |||
| // 在发送消息前,必须调用 start 方法来启动 Producer,只需调用一次即可 | |||
| producer.start(); | |||
| log.info("aliyunrocketmq producer info :"+JSON.toJSONString(producer)); | |||
| producerMap.put(topic.getCode(), producer); | |||
| } | |||
| } | |||
| @Override | |||
| public void sendMessage(BaseMsg data, String topic, String tags, String keys) { | |||
| Producer producer = producerMap.get(topic); | |||
| if (null == producer) { | |||
| log.error("topic :"+topic+" has no AliyunRocketMqMessageProducer."); | |||
| return; | |||
| } | |||
| if (producer.isClosed()) { | |||
| producer.start(); | |||
| } | |||
| @@ -32,5 +32,10 @@ public interface WxOrderGroupService { | |||
| List<WxOrderGroup> findList(WxOrderGroup group); | |||
| PageInfo<WxOrderGroupMarketing> queryOrderGroupMarketingList(WxOrderGroupMarketing marketing, Integer pageNum, Integer pageSize); | |||
| /** | |||
| * 支付成功之后,更新接口调用 | |||
| */ | |||
| void afterPaySuccessUpdate(WxOrder order); | |||
| } | |||
| @@ -226,5 +226,8 @@ public interface WxOrderService { | |||
| * H5支付后, 券再注入 | |||
| */ | |||
| Long saveOuterOrderForCoupon(WxCUser user, WxCoupon coupon, Long couponChannelId, String formId, Long couponPasswordId); | |||
| int countGroupOrder(Long groupId,boolean ignoreUnPay); | |||
| } | |||
| @@ -65,6 +65,59 @@ public class WxOrderGroupServiceImpl implements WxOrderGroupService { | |||
| @Autowired | |||
| WxCouponChannelMapper wxCouponChannelMapper; | |||
| @Override | |||
| public void afterPaySuccessUpdate(WxOrder order) { | |||
| // 参与拼团 | |||
| WxOrderGroup wxOrderGroup = wxOrderGroupMapper.selectById(order.getOrderGroupId()); | |||
| if (null == wxOrderGroup) { | |||
| //错误,更新状态,定时任务会发起退款,回滚库存 | |||
| order.setOrderStatus(EnumOrderStatus.ORDER_STATUS_COOPERATING_UNPAID.getCode()); | |||
| wxOrderMapper.updateById(order); | |||
| throw new MallinkException(ErrorCode.ORDER_GROUP_COOPERATING_FAILD.getCode(),"WxOrderGroup is null."+order.getOrderGroupId()); | |||
| } | |||
| WxCoupon wxCoupon = wxCouponMapper.selectById(order.getProductId()); | |||
| if (null == wxCoupon) { | |||
| throw new MallinkException(ErrorCode.ORDER_GROUP_COOPERATING_FAILD.getCode(),"WxCoupon is null. orderId:"+order.getId()); | |||
| } | |||
| if (wxOrderGroup.getStatus() == EnumOrderStatus.ORDER_STATUS_COOPERATING_COMPLETE.getCode()) { | |||
| return; | |||
| } | |||
| int remainPeople = updateOrderGroup(wxOrderGroup,order,wxCoupon); | |||
| if (remainPeople == 0) { | |||
| actionAfterOrderGroupSuccess(order, order.getOrderGroupId()); | |||
| } | |||
| } | |||
| private int updateOrderGroup(WxOrderGroup wxOrderGroup,WxOrder order, WxCoupon wxCoupon) { | |||
| //锁住人数 | |||
| long time = System.currentTimeMillis() + RedisLock.LONG_TIMEOUT; | |||
| String timeStr = String.valueOf(time); | |||
| boolean grouppeopleLock = redisLock.lock("grouppeopleLock_"+order.getOrderGroupId(), timeStr); | |||
| if (!grouppeopleLock) { | |||
| throw new MallinkException(ErrorCode.ORDER_GROUP_COOPERATING_FAILD.getCode(),"参团锁定失败,请稍后再试。"); | |||
| } | |||
| //此处拼团数量应从订单总数查询 | |||
| int ordercount = wxOrderService.countGroupOrder(order.getOrderGroupId(),true); | |||
| Integer remainPeople = wxCoupon.getPressLimitNum()-ordercount; | |||
| //Integer remainPeople = wxOrderGroup.getRemainPeople()-1; | |||
| wxOrderGroup.setStatus(remainPeople <= 0 ? EnumOrderStatus.ORDER_STATUS_COOPERATING_COMPLETE.getCode() : wxOrderGroup.getStatus()); | |||
| wxOrderGroup.setUpdateDate(new Date()); | |||
| wxOrderGroup.setRemainPeople(remainPeople); | |||
| logger.info("非首次拼团,更新拼团信息, 剩余人数-1"); | |||
| int row = wxOrderGroupMapper.updateOrderGroup(wxOrderGroup); | |||
| if (row != 1) { | |||
| //错误,更新状态,定时任务会发起退款,回滚库存 | |||
| order.setOrderStatus(EnumOrderStatus.ORDER_STATUS_COOPERATING_UNPAID.getCode()); | |||
| wxOrderMapper.updateById(order); | |||
| redisLock.unlock("grouppeopleLock_"+order.getOrderGroupId(), timeStr); | |||
| throw new MallinkException(ErrorCode.ORDER_GROUP_COOPERATING_FAILD.getCode(),"参团失败,将稍后退款."); | |||
| }else { | |||
| redisLock.unlock("grouppeopleLock_"+order.getOrderGroupId(), timeStr); | |||
| } | |||
| return remainPeople; | |||
| } | |||
| @Override | |||
| @Transactional(propagation = Propagation.REQUIRED, rollbackFor = {Exception.class}) | |||
| public void createOrderGroup(WxOrder order, WxCoupon wxCoupon) { | |||
| @@ -75,27 +128,20 @@ public class WxOrderGroupServiceImpl implements WxOrderGroupService { | |||
| // 参与拼团 | |||
| WxOrderGroup wxOrderGroup = wxOrderGroupMapper.selectById(orderGroupId); | |||
| if (null == wxOrderGroup) { | |||
| //错误,更新状态,定时任务会发起退款 | |||
| order.setOrderStatus(EnumOrderStatus.ORDER_STATUS_COOPERATING_FAILD.getCode()); | |||
| //错误,更新状态,定时任务会发起退款,回滚库存 | |||
| order.setOrderStatus(EnumOrderStatus.ORDER_STATUS_COOPERATING_UNPAID.getCode()); | |||
| wxOrderMapper.updateById(order); | |||
| throw new MallinkException(ErrorCode.ORDER_GROUP_COOPERATING_FAILD.getCode(),"WxOrderGroup is null."+orderGroupId); | |||
| } | |||
| if(wxOrderGroup.getRemainPeople()<1) { | |||
| //错误,更新状态,定时任务会发起退款 | |||
| order.setOrderStatus(EnumOrderStatus.ORDER_STATUS_COOPERATING_FAILD.getCode()); | |||
| //错误,更新状态,定时任务会发起退款,回滚库存 | |||
| order.setOrderStatus(EnumOrderStatus.ORDER_STATUS_COOPERATING_UNPAID.getCode()); | |||
| wxOrderMapper.updateById(order); | |||
| throw new MallinkException(ErrorCode.ORDER_GROUP_COOPERATING_FAILD.getCode(),"参团人数已满,将稍后退款。"); | |||
| } | |||
| Integer remainPeople = wxOrderGroup.getRemainPeople()-1; | |||
| wxOrderGroup.setStatus(remainPeople == 0 ? EnumOrderStatus.ORDER_STATUS_COOPERATING_COMPLETE.getCode() : wxOrderGroup.getStatus()); | |||
| wxOrderGroup.setUpdateDate(new Date()); | |||
| logger.info("非首次拼团,更新拼团信息, 剩余人数-1"); | |||
| int row = wxOrderGroupMapper.updateOrderGroup(wxOrderGroup); | |||
| if (row != 1) { | |||
| //TODO 这个时候应该要发起异步退款。 | |||
| throw new MallinkException(ErrorCode.ORDER_GROUP_COOPERATING_FAILD.getCode(),"参团失败,将稍后退款."); | |||
| } | |||
| int remainPeople = updateOrderGroup(wxOrderGroup,order,wxCoupon); | |||
| // 更新订单信息 | |||
| order.setOrderStatus(wxOrderGroup.getStatus()); | |||
| order.setPressEndDate(wxOrderGroup.getExpiredDate()); | |||
| @@ -382,4 +428,5 @@ public class WxOrderGroupServiceImpl implements WxOrderGroupService { | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @@ -28,6 +28,7 @@ import org.springframework.transaction.annotation.Transactional; | |||
| import com.alibaba.fastjson.JSON; | |||
| import com.alibaba.fastjson.JSONObject; | |||
| import com.baomidou.mybatisplus.core.conditions.Wrapper; | |||
| import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; | |||
| import com.github.pagehelper.PageHelper; | |||
| import com.github.pagehelper.PageInfo; | |||
| @@ -505,7 +506,7 @@ public class WxOrderServiceImpl implements WxOrderService { | |||
| * @param wxCouponSendVo | |||
| */ | |||
| private void stockMerchantReduce(WxCUser user, WxCoupon coupon, String couponIdStr, WxCouponSendVo wxCouponSendVo) { | |||
| long time = System.currentTimeMillis() + RedisLock.TIMEOUT; | |||
| long time = System.currentTimeMillis() + RedisLock.LONG_TIMEOUT; | |||
| String timeStr = String.valueOf(time); | |||
| // 库存加锁 | |||
| if (!redisLock.lock(couponIdStr, timeStr)) { | |||
| @@ -621,13 +622,13 @@ public class WxOrderServiceImpl implements WxOrderService { | |||
| } | |||
| if (count >= coupon.getUseLimitQuantity()) { | |||
| logger.error("此券购买数量已超限, couponId: " + couponIdStr + ", count: " + count); | |||
| throw new MallinkException(ErrorCode.ORDER_IS_LIMITED); | |||
| throw new MallinkException(ErrorCode.ORDER_IS_LIMITED.getCode(),"此券购买数量已超限, couponId: " + couponIdStr + ", count: " + count); | |||
| } | |||
| try { | |||
| //减库存,从redis中取,然后发mq消息同步到数据库 | |||
| long stock = redisLock.decrease(EnumCacheKey.COUPON_STOCK.getMessage()+coupon.getId(), 1); | |||
| if (stock <= 0 ) { | |||
| if (stock < 0 ) { | |||
| throw new MallinkException(ErrorCode.ORDER_IS_FAIL.getCode(),"券库存已为零!"); | |||
| } | |||
| UpdateCouponStockMsg msg = new UpdateCouponStockMsg(); | |||
| @@ -637,8 +638,8 @@ public class WxOrderServiceImpl implements WxOrderService { | |||
| msg.setMsgType(EnumMsgRecordType.COUPON_STOCK.getCode()); | |||
| mqBaseProducer.sendMessage(msg, EnumMsgMqTopic.STOCK.getCode(), "*", "decrease_stock_"+coupon.getId()); | |||
| } catch (RuntimeException e) { | |||
| logger.error("此券减库存失败, couponId: " + couponIdStr); | |||
| throw new MallinkException(ErrorCode.ORDER_IS_FAIL); | |||
| logger.error("此券减库存失败, couponId: " + couponIdStr,e); | |||
| throw new MallinkException(ErrorCode.ORDER_IS_FAIL.getCode(),e.getMessage()); | |||
| } | |||
| } | |||
| @@ -737,7 +738,7 @@ public class WxOrderServiceImpl implements WxOrderService { | |||
| Long couponId = updateOrder.getProductId(); | |||
| String couponIdStr = "" + couponId; | |||
| //加锁 | |||
| long time = System.currentTimeMillis() + 300*RedisLock.TIMEOUT; | |||
| long time = System.currentTimeMillis() + RedisLock.LONG_TIMEOUT; | |||
| String timeStr = String.valueOf(time); | |||
| if (!redisLock.lock(couponIdStr, timeStr)) { | |||
| @@ -1006,86 +1007,102 @@ public class WxOrderServiceImpl implements WxOrderService { | |||
| if (coupon.getType().equals(EnumCouponType.CARD_MULTIMCH.getCode())) { | |||
| isCard = true; | |||
| } | |||
| final IdWorker idWorker = IdWorker.get(); | |||
| WxCouponOrder couponOrder = new WxCouponOrder(); | |||
| couponOrder.setId(idWorker.nextId()); | |||
| couponOrder.updateTenantInfo(order); | |||
| couponOrder.setCouponId(order.getProductId()); | |||
| couponOrder.setCouponType(coupon.getType()); | |||
| couponOrder.setCUserId(user.getId()); | |||
| couponOrder.setOwnerId(user.getId()); | |||
| couponOrder.setAutoRefund(coupon.getAutoRefund()); | |||
| couponOrder.setOrderId(order.getOrderNumber()); | |||
| couponOrder.setExpiredTime(valid_date); | |||
| if (!isCard) { | |||
| couponOrder.setCouponOrderStatus(EnumCouponOrderStatus.COUPON_ORDER_USE_WAIT.getCode()); | |||
| } else { | |||
| couponOrder.setCouponOrderStatus(EnumCouponOrderStatus.CARD_USING.getCode()); | |||
| //TODO 如果orderId已经存在,则不再添加 | |||
| WxCouponOrder couponOrderQ = new WxCouponOrder(); | |||
| couponOrderQ.setOrderId(order.getId()); | |||
| WxCouponOrder couponOrder = null; | |||
| List<WxCouponOrder> couponorderlist = wxCouponOrderMapper.findList(couponOrderQ); | |||
| if (null != couponorderlist && couponorderlist.size() > 0 ) { | |||
| couponOrder = couponorderlist.get(0); | |||
| }else { | |||
| final IdWorker idWorker = IdWorker.get(); | |||
| couponOrder = new WxCouponOrder(); | |||
| couponOrder.setId(idWorker.nextId()); | |||
| couponOrder.updateTenantInfo(order); | |||
| couponOrder.setCouponId(order.getProductId()); | |||
| couponOrder.setCouponType(coupon.getType()); | |||
| couponOrder.setCUserId(user.getId()); | |||
| couponOrder.setOwnerId(user.getId()); | |||
| couponOrder.setAutoRefund(coupon.getAutoRefund()); | |||
| couponOrder.setOrderId(order.getOrderNumber()); | |||
| couponOrder.setExpiredTime(valid_date); | |||
| if (!isCard) { | |||
| couponOrder.setCouponOrderStatus(EnumCouponOrderStatus.COUPON_ORDER_USE_WAIT.getCode()); | |||
| } else { | |||
| couponOrder.setCouponOrderStatus(EnumCouponOrderStatus.CARD_USING.getCode()); | |||
| } | |||
| couponOrder.setCreateDate(curr); | |||
| couponOrder.setUpdateDate(curr); | |||
| couponOrder.setCouponPrice(order.getPayment()); | |||
| wxCouponOrderMapper.insert(couponOrder); | |||
| } | |||
| couponOrder.setCreateDate(curr); | |||
| couponOrder.setUpdateDate(curr); | |||
| couponOrder.setCouponPrice(order.getPayment()); | |||
| wxCouponOrderMapper.insert(couponOrder); | |||
| /// 储值卡信息添加 | |||
| if (isCard) { | |||
| Integer fee = 0; | |||
| WxCardInfo cardInfo = new WxCardInfo(); | |||
| cardInfo.setId(couponOrder.getId()); | |||
| cardInfo.updateTenantInfo(order); | |||
| cardInfo.setCouponId(order.getProductId()); | |||
| cardInfo.setAmount(coupon.getPrice()); | |||
| cardInfo.setSaleAmount(coupon.getSalePrice()); | |||
| cardInfo.setRemainingAmount(coupon.getPrice()); | |||
| if (!coupon.checkIsFree()) { | |||
| // 有价卡 | |||
| cardInfo.setTransactionId(payOrder.getTransactionId()); | |||
| if (payOrder.getShareAmount() != null) { | |||
| // 开启分账 | |||
| fee = payOrder.getPayAmount() - payOrder.getShareAmount(); | |||
| cardInfo.setShareFeeAmount(payOrder.getShareAmount()); | |||
| cardInfo.setRemainingShareFeeAmount(payOrder.getShareAmount()); | |||
| cardInfo.setRateAmount(payOrder.getRateAmount()); | |||
| } else { | |||
| // 未开启分账 | |||
| fee = PayUtils.getPayRate(payOrder.getPayAmount(), payAccount.getRate(), false); | |||
| Integer shareAmount = payOrder.getPayAmount() - fee; | |||
| cardInfo.setShareFeeAmount(shareAmount); | |||
| cardInfo.setRemainingShareFeeAmount(shareAmount); | |||
| if (payAccount.getRealRate() != null) { | |||
| int iRealChargeFee = PayUtils.getPayRate(payOrder.getPayAmount(), payAccount.getRealRate(), true); | |||
| if (fee > iRealChargeFee) { | |||
| cardInfo.setRateAmount(fee - iRealChargeFee); | |||
| } | |||
| } | |||
| } | |||
| } else { | |||
| // 免费卡 | |||
| cardInfo.setShareFeeAmount(0); | |||
| cardInfo.setRemainingShareFeeAmount(0); | |||
| cardInfo.setRateAmount(0); | |||
| if (coupon.getPasswordSupport().equals(EnumCouponPasswordSupport.SUPPORTED.getCode())) { | |||
| WxCouponPassword updateCPwd = new WxCouponPassword(); | |||
| updateCPwd.setId(couponPasswordId); | |||
| updateCPwd.setCardId(cardInfo.getId()); | |||
| updateCPwd.setStatus(EnumCouponPasswordStatus.USED.getCode()); | |||
| couponPasswordMapper.updateById(updateCPwd); | |||
| } | |||
| } | |||
| cardInfo.setServiceFeeAmount(fee); | |||
| cardInfo.setCreateDate(curr); | |||
| cardInfo.setUpdateDate(curr); | |||
| cardInfo.setSupportTransfer(coupon.getSupportTransfer()); | |||
| //检查卡是否下架,如果是,不可转赠 | |||
| WxCouponChannel wxCouponChannel = wxCouponChannelMapper.selectById(order.getCouponChannelId()); | |||
| if (wxCouponChannel != null && wxCouponChannel.getStatus().equals(EnumCouponChannelStatus.STATUS_TAKE_OFFF.getCode())) { | |||
| cardInfo.setSupportTransfer(EnumCouponTransfer.NO.getCode()); | |||
| } | |||
| wxCardInfoMapper.insert(cardInfo); | |||
| //判断该transctionId是否已经存在,如果存在,则不添加 | |||
| WxCardInfo cardInfoq = new WxCardInfo(); | |||
| cardInfoq.setTransactionId(payOrder.getTransactionId()); | |||
| List<WxCardInfo> cardInfoList = wxCardInfoMapper.findList(cardInfoq); | |||
| if (null != cardInfoList && cardInfoList.size() > 0) { | |||
| //do nothing | |||
| }else { | |||
| Integer fee = 0; | |||
| WxCardInfo cardInfo = new WxCardInfo(); | |||
| cardInfo.setId(couponOrder.getId()); | |||
| cardInfo.updateTenantInfo(order); | |||
| cardInfo.setCouponId(order.getProductId()); | |||
| cardInfo.setAmount(coupon.getPrice()); | |||
| cardInfo.setSaleAmount(coupon.getSalePrice()); | |||
| cardInfo.setRemainingAmount(coupon.getPrice()); | |||
| if (!coupon.checkIsFree()) { | |||
| // 有价卡 | |||
| cardInfo.setTransactionId(payOrder.getTransactionId()); | |||
| if (payOrder.getShareAmount() != null) { | |||
| // 开启分账 | |||
| fee = payOrder.getPayAmount() - payOrder.getShareAmount(); | |||
| cardInfo.setShareFeeAmount(payOrder.getShareAmount()); | |||
| cardInfo.setRemainingShareFeeAmount(payOrder.getShareAmount()); | |||
| cardInfo.setRateAmount(payOrder.getRateAmount()); | |||
| } else { | |||
| // 未开启分账 | |||
| fee = PayUtils.getPayRate(payOrder.getPayAmount(), payAccount.getRate(), false); | |||
| Integer shareAmount = payOrder.getPayAmount() - fee; | |||
| cardInfo.setShareFeeAmount(shareAmount); | |||
| cardInfo.setRemainingShareFeeAmount(shareAmount); | |||
| if (payAccount.getRealRate() != null) { | |||
| int iRealChargeFee = PayUtils.getPayRate(payOrder.getPayAmount(), payAccount.getRealRate(), true); | |||
| if (fee > iRealChargeFee) { | |||
| cardInfo.setRateAmount(fee - iRealChargeFee); | |||
| } | |||
| } | |||
| } | |||
| } else { | |||
| // 免费卡 | |||
| cardInfo.setShareFeeAmount(0); | |||
| cardInfo.setRemainingShareFeeAmount(0); | |||
| cardInfo.setRateAmount(0); | |||
| if (coupon.getPasswordSupport().equals(EnumCouponPasswordSupport.SUPPORTED.getCode())) { | |||
| WxCouponPassword updateCPwd = new WxCouponPassword(); | |||
| updateCPwd.setId(couponPasswordId); | |||
| updateCPwd.setCardId(cardInfo.getId()); | |||
| updateCPwd.setStatus(EnumCouponPasswordStatus.USED.getCode()); | |||
| couponPasswordMapper.updateById(updateCPwd); | |||
| } | |||
| } | |||
| cardInfo.setServiceFeeAmount(fee); | |||
| cardInfo.setCreateDate(curr); | |||
| cardInfo.setUpdateDate(curr); | |||
| cardInfo.setSupportTransfer(coupon.getSupportTransfer()); | |||
| //检查卡是否下架,如果是,不可转赠 | |||
| WxCouponChannel wxCouponChannel = wxCouponChannelMapper.selectById(order.getCouponChannelId()); | |||
| if (wxCouponChannel != null && wxCouponChannel.getStatus().equals(EnumCouponChannelStatus.STATUS_TAKE_OFFF.getCode())) { | |||
| cardInfo.setSupportTransfer(EnumCouponTransfer.NO.getCode()); | |||
| } | |||
| wxCardInfoMapper.insert(cardInfo); | |||
| } | |||
| } | |||
| return couponOrder; | |||
| } | |||
| @@ -2109,7 +2126,7 @@ public class WxOrderServiceImpl implements WxOrderService { | |||
| // 2. 拼团检查 | |||
| if (isOrderGroup(orderGroupId)) { | |||
| checkOrderGroup(user, orderGroupId); | |||
| checkOrderGroup(user, orderGroupId,coupon); | |||
| } | |||
| String couponIdStr = String.valueOf(coupon.getId()); | |||
| // 3. 减库存操作 | |||
| @@ -2240,16 +2257,27 @@ public class WxOrderServiceImpl implements WxOrderService { | |||
| return orderNumber; | |||
| } | |||
| private void checkOrderGroup(WxCUser user, Long orderGroupId) { | |||
| private void checkOrderGroup(WxCUser user, Long orderGroupId,WxCoupon coupon) { | |||
| WxOrderGroup group = wxOrderGroupMapper.selectById(orderGroupId); | |||
| if (group.getStatus().equals(EnumOrderStatus.ORDER_STATUS_COOPERATING_COMPLETE.getCode())) { | |||
| logger.error("下订单拼团人数已满>>>" + orderGroupId); | |||
| throw new MallinkException(ErrorCode.ORDER_GROUP_COOPERATING_FINISHED); | |||
| } | |||
| if (group.getRemainPeople()<=0) { | |||
| throw new MallinkException(ErrorCode.ORDER_GROUP_COOPERATING_FINISHED.getCode(),"下单人数已满"); | |||
| } | |||
| //判断拼团人数是否已经超出限制 | |||
| int groupCount = countGroupOrder(orderGroupId,false); | |||
| if (groupCount>=coupon.getPressLimitNum()) { | |||
| throw new MallinkException(ErrorCode.ORDER_GROUP_COOPERATING_FINISHED.getCode(),"下单人数超出优惠券人数限制!"); | |||
| } | |||
| WxOrder order = new WxOrder(); | |||
| order.setOrderGroupId(group.getId()); | |||
| order.setCUserId(user.getId()); | |||
| order.setOrderStatus(EnumOrderStatus.ORDER_STATUS_COOPERATING_UNPAID.getCode()); | |||
| //order.setOrderStatus(EnumOrderStatus.ORDER_STATUS_COOPERATING_UNPAID.getCode()); | |||
| long count = wxOrderMapper.selectCount(new QueryWrapper(order)); | |||
| if (count > 0) { | |||
| logger.error("重复的拼团>>>" + orderGroupId); | |||
| @@ -2261,5 +2289,20 @@ public class WxOrderServiceImpl implements WxOrderService { | |||
| return orderGroupId != null && !orderGroupId.equals(0L); | |||
| } | |||
| @Override | |||
| public int countGroupOrder(Long groupId,boolean ignoreUnPay) { | |||
| WxOrder query = new WxOrder(); | |||
| query.setOrderGroupId(groupId); | |||
| List<Integer> statusS = new ArrayList<Integer>(); | |||
| statusS.add(EnumOrderStatus.ORDER_STATUS_PAYMENT_SUCCESS.getCode()); | |||
| statusS.add(EnumOrderStatus.ORDER_STATUS_COOPERATING.getCode()); | |||
| statusS.add(EnumOrderStatus.ORDER_STATUS_COOPERATING_COMPLETE.getCode()); | |||
| if (!ignoreUnPay) { | |||
| statusS.add(EnumOrderStatus.ORDER_STATUS_COOPERATING_UNPAID.getCode()); | |||
| } | |||
| query.setStatusS(statusS); | |||
| return wxOrderMapper.countList(query); | |||
| } | |||
| } | |||
| @@ -124,6 +124,7 @@ public class WxPayOrderServiceImpl implements WxPayOrderService { | |||
| public void handleSuccessOrder(WxPayOrder oldRecord,WxOrder order,Map<String, String> retMap) { | |||
| Date curDate = new Date(); | |||
| if (oldRecord.getPayOrderStatus() != EnumPayStatus.PAY_STATUS_SUCCESS.getCode()) { | |||
| //因为此处是处理订单支付成功了但是订单状态为未支付成功的异常状态,库存不应该再扣减 | |||
| //更新wxPayOrder | |||
| oldRecord.setPayOrderStatus(EnumPayStatus.PAY_STATUS_SUCCESS.getCode()); | |||
| String timEndStr = retMap.get("time_end"); | |||
| @@ -179,7 +180,6 @@ public class WxPayOrderServiceImpl implements WxPayOrderService { | |||
| @Override | |||
| public WxPayOrder handleWxOrderQuery(WxPayOrder oldRecord,WxOrder order,WxAppinfo appInfo,WxPayAccount payAccount,IdWorker idworker,boolean repeatPay) { | |||
| //int wxpaystatus = WxPayOrderServiceHelper.wxOrderPayStatus(oldRecord, order, appInfo, payAccount); | |||
| Map<String, String> retMap = WxPayOrderServiceHelper.wxOrderPayStatusMap(oldRecord, order, appInfo, payAccount); | |||
| int wxpaystatus = WxPayOrderServiceHelper.getPayStatusFromMap(retMap, oldRecord.getPayOrderNo()); | |||
| if (EnumPayStatus.PAY_STATUS_SUCCESS.getCode()==wxpaystatus) { | |||
| @@ -200,12 +200,6 @@ public class WxPayOrderServiceImpl implements WxPayOrderService { | |||
| if (repeatPay) { | |||
| if (oldRecord.getPayOrderStatus()!=EnumPayStatus.PAY_STATUS_WAIT.getCode()) { | |||
| oldRecord.setPayOrderStatus(EnumPayStatus.PAY_STATUS_WAIT.getCode()); | |||
| Long payno = idworker.nextId(); | |||
| if (null == payno || payno.longValue() <=0) { | |||
| throw new MallinkException(ErrorCode.PAY_ORDER_PAYING.getCode(),"订单支付流水号生成失败!handleWxOrderQuery:oldRecord:"+oldRecord+":wxstatus:"+wxpaystatus); | |||
| } | |||
| oldRecord.setPayOrderNo(String.valueOf(payno)); | |||
| int sqlRow0 =wxPayOrderMapper.updateById(oldRecord); | |||
| if (sqlRow0 != 1) { | |||
| logger.error("pay order update error: " + oldRecord.toString()); | |||
| @@ -240,11 +234,19 @@ public class WxPayOrderServiceImpl implements WxPayOrderService { | |||
| WxOrder orderParams = new WxOrder(); | |||
| orderParams.setOrderGroupId(order.getOrderGroupId()); | |||
| orderParams.setCUserId(user.getId()); | |||
| orderParams.setOrderStatus(EnumOrderStatus.ORDER_STATUS_COOPERATING.getCode()); | |||
| int count = wxOrderMapper.selectCount(new QueryWrapper(orderParams)); | |||
| if (count > 0) { | |||
| logger.error("重复的拼团>>>" + order); | |||
| throw new MallinkException(ErrorCode.ORDER_GROUP_COOPERATING_ATTEND); | |||
| List<WxOrder> olist = wxOrderMapper.findList(orderParams); | |||
| if (olist == null || olist.size() <=0 ) { | |||
| throw new MallinkException(ErrorCode.ORDER_GROUP_COOPERATING_FAILD.getCode(),"未查询到参团订单[user:"+user.getId()+",groupId:"+order.getOrderGroupId()+"]"); | |||
| } | |||
| if (olist.size() != 1) { | |||
| throw new MallinkException(ErrorCode.ORDER_GROUP_COOPERATING_FAILD.getCode(),"参团订单多条[user:"+user.getId()+",groupId:"+order.getOrderGroupId()+"]"); | |||
| } | |||
| WxOrder orderq = olist.get(0); | |||
| if (null == orderq) { | |||
| throw new MallinkException(ErrorCode.ORDER_GROUP_COOPERATING_FAILD.getCode(),"未查询到参团订单[user:"+user.getId()+",groupId:"+order.getOrderGroupId()+"]"); | |||
| } | |||
| if (orderq.getOrderStatus()==EnumOrderStatus.ORDER_STATUS_COOPERATING.getCode()) { | |||
| throw new MallinkException(ErrorCode.ORDER_GROUP_COOPERATING_ATTEND.getCode(),"不能重复参团订单[user:"+user.getId()+",groupId:"+order.getOrderGroupId()+"]"); | |||
| } | |||
| } | |||
| @@ -349,12 +351,6 @@ public class WxPayOrderServiceImpl implements WxPayOrderService { | |||
| }else if(oldRecord.getPayOrderStatus()==EnumPayStatus.PAY_STATUS_FAIL.getCode()|| | |||
| oldRecord.getPayOrderStatus()==EnumPayStatus.PAY_STATUS_NOTPAY.getCode()) { | |||
| oldRecord.setPayOrderStatus(EnumPayStatus.PAY_STATUS_WAIT.getCode()); | |||
| //重新设置支付no | |||
| Long payno = idworker.nextId(); | |||
| if (null == payno || payno.longValue() <=0) { | |||
| throw new MallinkException(ErrorCode.PAY_ORDER_PAYING.getCode(),"订单支付流水号生成失败!service oldRecord:"+oldRecord); | |||
| } | |||
| oldRecord.setPayOrderNo(String.valueOf(payno)); | |||
| int sqlRow0 = wxPayOrderMapper.updateById(oldRecord); | |||
| if (sqlRow0 != 1) { | |||
| logger.error("pay order update error: " + record.toString()); | |||
| @@ -27,6 +27,8 @@ public class RedisLock { | |||
| public static final int TIMEOUT = 10*1000;//超时时间 10s | |||
| public static final int LONG_TIMEOUT = 3600*1000;//超长超时时间,关键业务点失败不能再进行下去的时间点 | |||
| /** | |||
| * 加锁 | |||
| * @param key productId - 商品的唯一标志 | |||
| @@ -123,7 +125,7 @@ public class RedisLock { | |||
| */ | |||
| public long decrease(String key, long delta) { | |||
| try { | |||
| stringRedisTemplate.opsForValue().decrement(key, delta); | |||
| return stringRedisTemplate.opsForValue().decrement(key, delta); | |||
| }catch(Exception e) { | |||
| logger.error("[Redis分布式锁] decrease error,{}",e); | |||
| } | |||
| @@ -147,6 +149,9 @@ public class RedisLock { | |||
| }catch(Exception e) { | |||
| logger.error("[Redis分布式锁] setCouponStock error,{}",e); | |||
| } | |||
| } | |||
| public boolean hasCouponStockCache(long couponId) { | |||
| return stringRedisTemplate.hasKey(EnumCacheKey.COUPON_STOCK.getMessage()+String.valueOf(couponId)); | |||
| } | |||
| } | |||
| @@ -25,7 +25,7 @@ | |||
| `share_fee_amount`,`remaining_share_fee_amount`, `rate_amount`, | |||
| `create_date`,`update_date`,`support_transfer` | |||
| </sql> | |||
| <sql id="dynamicWhereConditions"> | |||
| where 1 = 1 | |||
| <if test=" null != id "> | |||
| @@ -211,4 +211,10 @@ | |||
| update wx_card_info set support_transfer=0,update_date=now() where support_transfer=1 and coupon_id=#{couponId} | |||
| </update> | |||
| <select id="findList" parameterType="com.iformall.domain.po.WxCardInfo" resultMap="BaseResultMap"> | |||
| select <include refid="allColumns" /> | |||
| from wx_card_info | |||
| <include refid="dynamicWhereConditions" /> | |||
| </select> | |||
| </mapper> | |||
| @@ -133,7 +133,7 @@ | |||
| </select> | |||
| <select id="countList" parameterType="com.iformall.domain.po.WxOrder" resultType="java.lang.Integer"> | |||
| select count(*) from wx_order | |||
| select count(1) from wx_order | |||
| <include refid="dynamicWhereConditions"/> | |||
| </select> | |||
| @@ -28,7 +28,7 @@ spring: | |||
| # REDIS | |||
| redis: | |||
| host: 202.165.179.86 | |||
| host: 101.201.103.81 | |||
| port: 6379 | |||
| password: ENC(xPFDlgd6v8zUhJMbcKc0KmmQiqs9qHtk) | |||
| timeout: 3600 | |||
| @@ -91,7 +91,7 @@ wechat: | |||
| componentToken: "formall2018" | |||
| componentAesKey: "htKq8EjBMPNndfZQK9JiFojFaqFwFpw42VfeWFtx7HN" | |||
| redis: | |||
| host: 202.165.179.86 | |||
| host: 101.201.103.81 | |||
| port: 6379 | |||
| password: ENC(xPFDlgd6v8zUhJMbcKc0KmmQiqs9qHtk) | |||
| timeout: 3600 | |||