guomengjiao 3 mesi fa
parent
commit
769f7ff06a

+ 8 - 0
renren-admin/src/main/java/io/renren/common/canstant/QueueConstant.java

@@ -43,4 +43,12 @@ public interface QueueConstant {
     String ACTIVITY_ISSUE_POINTS_DEAD_KEY = "activity.issue.points.dead.key";
     String ACTIVITY_ISSUE_POINTS_DEAD_QUEUE = "activity.issue.points.dead.queue";
 
+    /**
+     * 企业会员
+     */
+    String ENTERPRISE_VIP_MS_QUEUE = "enterprise.vip.ms.queue";
+    String ENTERPRISE_VIP_DEAD_EX = "enterprise.vip.dead.ex";
+    String ENTERPRISE_VIP_DEAD_KEY = "enterprise.vip.dead.key";
+    String ENTERPRISE_VIP_DEAD_QUEUE = "enterprise.vip.dead.queue";
+
 }

+ 42 - 0
renren-admin/src/main/java/io/renren/common/config/RabbitEnterpriseVipMqConfig.java

@@ -0,0 +1,42 @@
+package io.renren.common.config;
+
+import io.renren.common.canstant.QueueConstant;
+import org.springframework.amqp.core.Binding;
+import org.springframework.amqp.core.BindingBuilder;
+import org.springframework.amqp.core.DirectExchange;
+import org.springframework.amqp.core.Queue;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import java.util.HashMap;
+
+@Configuration
+public class RabbitEnterpriseVipMqConfig {
+
+    @Bean
+    public Queue enterpriseVipMsQueue() {
+        HashMap<String, Object> map = new HashMap<>();
+        // 设置延迟的时间 设置消息死亡后走哪个交换机  走哪个路由key
+        map.put("x-message-ttl", Long.MAX_VALUE);
+        map.put("x-dead-letter-exchange", QueueConstant.ENTERPRISE_VIP_DEAD_EX);
+        map.put("x-dead-letter-routing-key", QueueConstant.ENTERPRISE_VIP_DEAD_KEY);
+        return new Queue(QueueConstant.ENTERPRISE_VIP_MS_QUEUE, true, false, false, map);
+    }
+
+    @Bean
+    public DirectExchange enterpriseVipDeadEx() {
+        return new DirectExchange(QueueConstant.ENTERPRISE_VIP_DEAD_EX);
+    }
+
+    @Bean
+    public Queue enterpriseVipDeadQueue() {
+        return new Queue(QueueConstant.ENTERPRISE_VIP_DEAD_QUEUE);
+    }
+
+    @Bean
+    public Binding enterpriseVipDeadBind() {
+        return BindingBuilder.bind(enterpriseVipDeadQueue()).to(enterpriseVipDeadEx()).with(QueueConstant.ENTERPRISE_VIP_DEAD_KEY);
+    }
+
+
+}

+ 46 - 0
renren-admin/src/main/java/io/renren/modules/listener/EnterpriseVipListener.java

@@ -0,0 +1,46 @@
+package io.renren.modules.listener;
+
+import cn.hutool.core.util.NumberUtil;
+import com.alibaba.fastjson.JSONObject;
+import com.rabbitmq.client.Channel;
+import io.renren.common.canstant.QueueConstant;
+import io.renren.common.enums.EnterpriseStatusEnum;
+import io.renren.modules.qmgj.dao.MemberInfoDao;
+import io.renren.modules.qmgj.entity.MemberInfoEntity;
+import io.renren.modules.qyh.entity.EnterpriseEntity;
+import io.renren.modules.qyh.service.EnterpriseService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.amqp.core.Message;
+import org.springframework.amqp.rabbit.annotation.RabbitListener;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
+import java.io.IOException;
+import java.time.LocalDate;
+
+@Component
+@Slf4j
+public class EnterpriseVipListener {
+
+    @Resource
+    private EnterpriseService enterpriseService;
+
+    @RabbitListener(queues = QueueConstant.ENTERPRISE_VIP_DEAD_QUEUE)
+    public void handlerDeadMsg(Message message, Channel channel) {
+        String s = new String(message.getBody());
+        JSONObject jsonObject = JSONObject.parseObject(s);
+        Long id = Long.parseLong(jsonObject.get("enterpriseId").toString());
+        EnterpriseEntity enterpriseEntity = enterpriseService.getById(id);
+        try {
+            if(!LocalDate.now().equals(enterpriseEntity.getExpiredTime().toLocalDate())) {
+                log.info("该企业已成功续费会员");
+                channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
+            }
+            enterpriseEntity.setStatus(EnterpriseStatusEnum.EXPIRED.value());
+            enterpriseService.updateById(enterpriseEntity);
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+    }
+
+}

+ 5 - 0
renren-admin/src/main/java/io/renren/modules/qmgj/entity/WgFillInfoEntity.java

@@ -92,4 +92,9 @@ public class WgFillInfoEntity implements Serializable {
 	 * 充终身会员赠送的积分
 	 */
 	private BigDecimal lifelongBonusPoints;
+
+	/**
+	 * 企业一年价格
+	 */
+	private BigDecimal enterprisePerYearPrice;
 }

+ 31 - 0
renren-admin/src/main/java/io/renren/modules/qyh/api/ApiEnterpriseController.java

@@ -1,5 +1,7 @@
 package io.renren.modules.qyh.api;
 
+import cn.hutool.core.map.MapUtil;
+import cn.hutool.core.util.StrUtil;
 import io.renren.common.annotation.RepeatSubmit;
 import io.renren.common.enums.EnterpriseStatusEnum;
 import io.renren.common.utils.Constant;
@@ -12,8 +14,11 @@ import io.swagger.annotations.ApiImplicitParam;
 import io.swagger.annotations.ApiImplicitParams;
 import io.swagger.annotations.ApiOperation;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.MediaType;
 import org.springframework.web.bind.annotation.*;
 
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
 import java.util.Map;
 
 /**
@@ -76,4 +81,30 @@ public class ApiEnterpriseController {
     public R apiInfo(@PathVariable("id") Long id) {
         return R.ok().put("data", enterpriseService.apiInfo(id));
     }
+
+    /**
+     * 开通或续费会员
+     */
+    @ResponseBody
+    @RequestMapping("/apiOpenVip")
+    public R openVip(@RequestBody Map<String, Object> params) {
+        if (params == null || params.get("id") == null) {
+            return R.error("缺少参数");
+        }
+        long id = Long.parseLong(params.get("id").toString());
+        String code = MapUtil.getStr(params, "code");
+        if (StrUtil.isBlank(code)) {
+            return R.error("缺少参数");
+        }
+        return enterpriseService.openOrVip(id, code);
+    }
+
+    /**
+     * 会员支付回调
+     */
+    @RequestMapping(value = "enterprisePaysCallback", produces = MediaType.APPLICATION_JSON_VALUE)
+    @ResponseBody
+    public String enterprisePaysCallback(HttpServletRequest request, HttpServletResponse response) throws Exception {
+        return enterpriseService.enterprisePaysCallback(request, response);
+    }
 }

+ 6 - 0
renren-admin/src/main/java/io/renren/modules/qyh/service/EnterpriseService.java

@@ -2,10 +2,13 @@ package io.renren.modules.qyh.service;
 
 import com.baomidou.mybatisplus.extension.service.IService;
 import io.renren.common.utils.PageUtils;
+import io.renren.common.utils.R;
 import io.renren.modules.qyh.entity.EnterpriseEntity;
 import io.renren.modules.qyh.model.dto.EnterpriseDTO;
 import io.renren.modules.qyh.model.vo.EnterpriseVO;
 
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
 import java.util.Map;
 
 /**
@@ -35,5 +38,8 @@ public interface EnterpriseService extends IService<EnterpriseEntity> {
 
     EnterpriseEntity apiInfo(Long id);
 
+    R openOrVip(Long id, String code);
+
+    String enterprisePaysCallback(HttpServletRequest request, HttpServletResponse response) throws Exception;
 }
 

+ 169 - 4
renren-admin/src/main/java/io/renren/modules/qyh/service/impl/EnterpriseServiceImpl.java

@@ -1,35 +1,62 @@
 package io.renren.modules.qyh.service.impl;
 
+import cn.hutool.core.lang.Snowflake;
 import cn.hutool.core.map.MapUtil;
 import cn.hutool.core.util.NumberUtil;
+import cn.hutool.core.util.ObjectUtil;
+import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import io.renren.common.enums.AuditCodeEnum;
-import io.renren.common.enums.AuditStatusEnum;
-import io.renren.common.enums.EnterpriseStatusEnum;
-import io.renren.common.enums.IsDeleteEnum;
+import com.github.wxpay.sdk.WXPayUtil;
+import io.renren.common.canstant.QueueConstant;
+import io.renren.common.enums.*;
 import io.renren.common.exception.RRException;
 import io.renren.common.utils.Constant;
 import io.renren.common.utils.PageUtils;
+import io.renren.common.utils.R;
+import io.renren.common.utils.RedisUtils;
+import io.renren.common.utils.config.PropertiesParameter;
 import io.renren.modules.qmgj.entity.MemberInfoEntity;
+import io.renren.modules.qmgj.entity.WgFillInfoEntity;
+import io.renren.modules.qmgj.service.WgFillInfoService;
+import io.renren.modules.qmgj.wxpayutil.OurWxPayConfig;
+import io.renren.modules.qmgj.wxpayutil.PayCommonUtil;
+import io.renren.modules.qmgj.wxpayutil.StringUtil;
+import io.renren.modules.qmjz.entity.WxConsumeInfoEntity;
+import io.renren.modules.qmjz.service.WxConsumeInfoService;
 import io.renren.modules.qmjz.utils.BeanCopyUtils;
 import io.renren.modules.qyh.entity.AuditEntity;
 import io.renren.modules.qyh.entity.EnterpriseEntity;
+import io.renren.modules.qyh.entity.OrderEntity;
 import io.renren.modules.qyh.mapper.EnterpriseMapper;
+import io.renren.modules.qyh.model.bo.PayForBO;
 import io.renren.modules.qyh.model.dto.AuditDTO;
 import io.renren.modules.qyh.model.dto.EnterpriseDTO;
 import io.renren.modules.qyh.model.vo.EnterpriseVO;
 import io.renren.modules.qyh.service.AuditService;
 import io.renren.modules.qyh.service.EnterpriseService;
 import io.renren.modules.qyh.service.LoginVerificationService;
+import io.renren.modules.qyh.service.OrderService;
+import org.jdom.JDOMException;
+import org.springframework.amqp.core.MessageProperties;
+import org.springframework.amqp.rabbit.core.RabbitTemplate;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
 import java.math.BigDecimal;
+import java.nio.charset.StandardCharsets;
+import java.time.Duration;
 import java.time.LocalDateTime;
+import java.util.Date;
+import java.util.HashMap;
 import java.util.Map;
 
 /**
@@ -43,6 +70,16 @@ public class EnterpriseServiceImpl extends ServiceImpl<EnterpriseMapper, Enterpr
     private AuditService auditService;
     @Autowired
     private LoginVerificationService loginVerificationService;
+    @Autowired
+    private WgFillInfoService wgFillInfoService;
+    @Autowired
+    private OrderService orderService;
+    @Autowired
+    private WxConsumeInfoService wxConsumeInfoService;
+    @Autowired
+    private RabbitTemplate rabbitTemplate;
+    @Autowired
+    private RedisUtils redisUtils;
 
     @Override
     public PageUtils queryPage(Map<String, Object> params) {
@@ -203,6 +240,134 @@ public class EnterpriseServiceImpl extends ServiceImpl<EnterpriseMapper, Enterpr
         return enterprise;
     }
 
+    @Transactional(rollbackFor = Exception.class)
+    @Override
+    public R openOrVip(Long id, String code) {
+        EnterpriseEntity enterpriseEntity = getById(id);
+        if (ObjectUtil.isNull(enterpriseEntity)) {
+            throw new RRException("企业id不存在");
+        }
+        // 查询所需付款
+        WgFillInfoEntity wgFillInfoEntity = wgFillInfoService.info();
+        BigDecimal enterprisePerYearPrice = wgFillInfoEntity.getEnterprisePerYearPrice();
+        //价格小于等于0就报错
+        if (enterprisePerYearPrice.compareTo(BigDecimal.ZERO) <= 0) {
+            return R.error("微信支付异常!");
+        }
+        MemberInfoEntity memberInfoEntity = loginVerificationService.verificationMemberId(enterpriseEntity.getMemberId());
+        try {
+            // 插入一条订单
+            String notifyUrl = PropertiesParameter.PROP.getProperty("pay.notify.enterprise.url");
+            PayForBO bo = new PayForBO();
+            bo.setNotifyUrl(notifyUrl);
+            bo.setOpenid(memberInfoEntity.getOpenid());
+            bo.setMemberId(memberInfoEntity.getId());
+            bo.setBusinessId(enterpriseEntity.getId());
+            bo.setBusinessType(OrderBusinessTypeEnum.ENTERPRISE_PAYMENT.value());
+            bo.setBuyContent(OrderBusinessTypeEnum.ENTERPRISE_PAYMENT.desc());
+            bo.setPayTime(LocalDateTime.now());
+            bo.setPrice(enterprisePerYearPrice);
+            bo.setActuallyPaid(enterprisePerYearPrice);
+            return R.ok().put("map", orderService.payFor(bo));
+        } catch (Exception e) {
+            throw new RRException("微信支付异常!", e);
+        }
+    }
+
+    @Transactional(rollbackFor = Exception.class)
+    @Override
+    public String enterprisePaysCallback(HttpServletRequest request, HttpServletResponse response) throws Exception {
+        Map<String, String> params = null;
+        try {
+            InputStream inStream = request.getInputStream();
+            ByteArrayOutputStream outSteam = new ByteArrayOutputStream();
+            byte[] buffer = new byte[1024];
+            int len = 0;
+            while ((len = inStream.read(buffer)) != -1) {
+                outSteam.write(buffer, 0, len);
+            }
+            String resultxml = new String(outSteam.toByteArray(), StandardCharsets.UTF_8);
+            params = PayCommonUtil.doXMLParse(resultxml);
+            outSteam.close();
+            inStream.close();
+        } catch (IOException | JDOMException e) {
+            e.printStackTrace();
+        }
+        Map<String, String> returnData = new HashMap<String, String>();
+        OurWxPayConfig ourWxPayConfig = new OurWxPayConfig();
+        if (!WXPayUtil.isSignatureValid(params, ourWxPayConfig.getKey())) {
+            // 支付失败
+            System.err.println("支付失败!");
+            returnData.put("return_code", "FAIL");
+            returnData.put("return_msg", "return_code不正确");
+            return StringUtil.GetMapToXML(returnData);
+        }
+        // 处理业务开始
+        String payNo = (String) params.get("out_trade_no");
+        // 交易订单号
+        String wxOrderNo = (String) params.get("transaction_id");
+        // 商户号
+        String wxMchId = (String) params.get("mch_id");
+        // 订单金额
+        String totalFee = (String) params.get("total_fee");
+        OrderEntity orderEntity = orderService.loadByPayNo(payNo, false);
+        if (orderEntity == null) {
+            // 支付失败
+            returnData.put("return_code", "FAIL");
+            returnData.put("return_msg", "return_code不正确");
+            return StringUtil.GetMapToXML(returnData);
+        }
+        String bussNo = new Snowflake().nextIdStr();
+        orderEntity.setPayStatus(YnEnum.YES.value());
+        orderEntity.setBussNo(bussNo);
+        orderService.updateById(orderEntity);
+
+        Long vipid = orderEntity.getBusinessId();
+
+        WxConsumeInfoEntity wxConsumeInfoEntity = new WxConsumeInfoEntity();
+
+        EnterpriseEntity enterpriseEntity = getById(vipid);
+        LocalDateTime now = LocalDateTime.now();
+        // 修复续期逻辑:如果当前已缴费且未过期,则在原到期时间基础上累加一年;否则从当前时间开始算一年
+        LocalDateTime expireTime;
+        if (enterpriseEntity.getExpiredTime() != null && enterpriseEntity.getExpiredTime().isAfter(now)) {
+            expireTime = enterpriseEntity.getExpiredTime().plusYears(1);
+        } else {
+            expireTime = now.plusYears(1);
+        }
+        enterpriseEntity.setStatus(EnterpriseStatusEnum.PAID.value());
+        enterpriseEntity.setExpiredTime(expireTime);
+        enterpriseEntity.setPayLastTime(now);
+        baseMapper.updateById(enterpriseEntity);
+
+        // 年费时发送mq
+        JSONObject jsonObject = new JSONObject();
+        jsonObject.put("enterpriseId", vipid);
+        rabbitTemplate.convertAndSend(QueueConstant.ENTERPRISE_VIP_MS_QUEUE, jsonObject.toString(), message -> {
+            MessageProperties messageProperties = message.getMessageProperties();
+            Duration between = Duration.between(now, expireTime);
+            messageProperties.setExpiration(String.valueOf(between.toMillis()));
+            return message;
+        });
+        wxConsumeInfoEntity.setBussNo(bussNo);
+        wxConsumeInfoEntity.setBussType(String.valueOf(orderEntity.getBusinessType()));
+        wxConsumeInfoEntity.setWxOrderNo(wxOrderNo);
+        wxConsumeInfoEntity.setWxMchId(wxMchId);
+        wxConsumeInfoEntity.setMoney(NumberUtil.toBigDecimal(totalFee));
+        wxConsumeInfoEntity.setInputime(new Date());
+        wxConsumeInfoEntity.setIsread("0");
+        wxConsumeInfoEntity.setIsdelete("0");
+        wxConsumeInfoEntity.setBusinessId(enterpriseEntity.getId());
+        wxConsumeInfoService.save(wxConsumeInfoEntity);
+
+        returnData.put("return_code", "SUCCESS");
+        returnData.put("return_msg", "OK");
+
+        // 支付成功 把订单号插入到redis里面,前端请求接口查看支付状态,有效期七天
+        redisUtils.set("orderNo:" + payNo, "企业会员订单编号", 7 * 60 * 60 * 24);
+        return StringUtil.GetMapToXML(returnData);
+    }
+
     private void validateEnterpriseExists(EnterpriseDTO dto) {
         Integer memberCount = baseMapper.selectCount(
                 new LambdaQueryWrapper<EnterpriseEntity>().eq(EnterpriseEntity::getMemberId, dto.getMemberId())

+ 1 - 0
renren-admin/src/main/resources/mapper/qmgj/WgFillInfoDao.xml

@@ -20,6 +20,7 @@
         <result property="lifelongPrice" column="lifelong_price"/>
         <result property="yearlyBonusPoints" column="yearly_bonus_points"/>
         <result property="lifelongBonusPoints" column="lifelong_bonus_points"/>
+        <result property="enterprisePerYearPrice" column="enterprise_per_year_price"/>
     </resultMap>
 
     <!--查询所有补缺内容  【全部案例库列表】-->

+ 1 - 0
renren-admin/src/main/resources/pay.properties

@@ -13,6 +13,7 @@ pay.notify.member.url=https://qingyunhui.songlanyun.com/qyh/api/member/memberPay
 pay.notify.meet.url=https://qingyunhui.songlanyun.com/qyh/api/order/meetPayCallback
 ## 活动支付回调地址
 pay.notify.activity.url=https://qingyunhui.songlanyun.com/qyh/api/act/register/wx/back
+pay.notify.enterprise.url=https://qingyunhui.songlanyun.com/qyh/api/enterprise/enterprisePaysCallback
 
 
 # 本地 退款P12文件目录

+ 6 - 0
renren-admin/src/main/resources/templates/modules/qmgj/wgfillinfo.html

@@ -127,6 +127,12 @@
                     <input type="text" class="form-control" v-model="wgFillInfo.lifelongBonusPoints" placeholder="请输入赠送积分" oninput="intnum(this)"/>
                 </div>
             </div>
+            <div class="form-group">
+                <div class="col-sm-2 control-label">青创生长企业(一年)</div>
+                <div class="col-sm-4">
+                    <input type="text" class="form-control" v-model="wgFillInfo.enterprisePerYearPrice" placeholder="请输入会员价格" oninput="num(this)"/>
+                </div>
+            </div>
             <div class="form-group">
                 <div class="col-sm-2 control-label"></div>
                 <input type="button" class="btn btn-primary" id="btnSaveOrUpdate" data-loading-text="保存中..."