|
|
@@ -1,7 +1,14 @@
|
|
|
package com.cyksj.service.order.impl;
|
|
|
|
|
|
import cn.hutool.core.date.DateField;
|
|
|
+import cn.hutool.core.date.DateTime;
|
|
|
import cn.hutool.core.date.DateUtil;
|
|
|
+import com.alipay.api.*;
|
|
|
+import com.alipay.api.domain.AlipayTradePagePayModel;
|
|
|
+import com.alipay.api.domain.AlipayTradeWapPayModel;
|
|
|
+import com.alipay.api.internal.util.AlipaySignature;
|
|
|
+import com.alipay.api.request.AlipayTradePagePayRequest;
|
|
|
+import com.alipay.api.request.AlipayTradeWapPayRequest;
|
|
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
|
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
|
|
import com.cyksj.common.EnvCommonService;
|
|
|
@@ -12,8 +19,12 @@ import com.cyksj.common.task.GlobalThreadPoolTaskExecutor;
|
|
|
import com.cyksj.common.util.Codec;
|
|
|
import com.cyksj.common.util.Jsons;
|
|
|
import com.cyksj.config.WeChatConfig;
|
|
|
+import com.cyksj.config.zfb.BaseZfbConfig;
|
|
|
+import com.cyksj.config.zfb.ZfbConfig;
|
|
|
+import com.cyksj.config.zfb.ZfbProductCode;
|
|
|
import com.cyksj.dto.RedisKey;
|
|
|
import com.cyksj.mapper.*;
|
|
|
+import com.cyksj.model.dto.AliPayParams;
|
|
|
import com.cyksj.model.dto.H5JsPayParams;
|
|
|
import com.cyksj.model.dto.WxMpTemplateData;
|
|
|
import com.cyksj.model.dto.WxMpTemplateMessage;
|
|
|
@@ -34,6 +45,7 @@ import org.springframework.stereotype.Service;
|
|
|
import org.springframework.transaction.annotation.Transactional;
|
|
|
|
|
|
import java.math.BigDecimal;
|
|
|
+import java.math.RoundingMode;
|
|
|
import java.util.Date;
|
|
|
import java.util.List;
|
|
|
import java.util.Map;
|
|
|
@@ -55,476 +67,629 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
|
|
|
|
|
|
private static final GlobalThreadPoolTaskExecutor THREAD_POOL_TASK_EXECUTOR = GlobalThreadPoolTaskExecutor.getInstance();
|
|
|
|
|
|
- private static final Sequence SEQUENCE = new Sequence(0);
|
|
|
+ private static final Sequence SEQUENCE = new Sequence(0);
|
|
|
|
|
|
- private final WeChatConfig weChatConfig;
|
|
|
-
|
|
|
- private final UserMapper userMapper;
|
|
|
+ private final WeChatConfig weChatConfig;
|
|
|
+
|
|
|
+ private final UserMapper userMapper;
|
|
|
|
|
|
- private final WeChatService weChatService;
|
|
|
-
|
|
|
- private final RedisService redisService;
|
|
|
-
|
|
|
- private final GoodsDonSkuMapper goodsDonSkuMapper;
|
|
|
-
|
|
|
- private final GoodsDonMapper goodsDonMapper;
|
|
|
-
|
|
|
- private final GroupsRelationMapper groupsRelationMapper;
|
|
|
-
|
|
|
- private final BeanSearcher beanSearcher;
|
|
|
-
|
|
|
- private final GroupsMapper groupsMapper;
|
|
|
-
|
|
|
- private final JobManager jobManager;
|
|
|
-
|
|
|
- private final OrderDonTransportMapper orderDonTransportMapper;
|
|
|
-
|
|
|
- private final AddressMapper addressMapper;
|
|
|
-
|
|
|
- private final OrderDonTransportMapper transportMapper;
|
|
|
-
|
|
|
- private final OrderDonWaybillMapper waybillMapper;
|
|
|
-
|
|
|
- private final OrderDonMapper orderDonMapper;
|
|
|
-
|
|
|
- private final EnvCommonService envCommonService;
|
|
|
-
|
|
|
- private static final GlobalThreadPoolTaskExecutor TASK_POOL = GlobalThreadPoolTaskExecutor.getInstance();
|
|
|
-
|
|
|
- private final CustomerServiceMapper customerServiceMapper;
|
|
|
-
|
|
|
-
|
|
|
- @Transactional(rollbackFor = Throwable.class)
|
|
|
- @Override
|
|
|
- public OrderDon submit(OrderPayRequest payRequest) {
|
|
|
- User user = userMapper.selectById(payRequest.getUserId());
|
|
|
- GoodsDonSku sku = goodsDonSkuMapper.selectById(payRequest.getSkuId());
|
|
|
- GoodsDon goodsDon = goodsDonMapper.selectById(sku.getGoodsId());
|
|
|
- if (goodsDon == null || !goodsDon.getStatus()) {
|
|
|
- throw new BusinessRuntimeException("商品已下架");
|
|
|
- }
|
|
|
- String payOpenId = user.getOpenId();
|
|
|
-
|
|
|
- Long relationId = 0L;
|
|
|
-
|
|
|
- if(goodsDon.getType() == 1){
|
|
|
- GroupsRelation relation = null;
|
|
|
- //锁定座位
|
|
|
- if (payRequest.getRelationId() != null && payRequest.getRelationId() > 0) {
|
|
|
- relation = groupsRelationMapper.selectById(payRequest.getRelationId());
|
|
|
- if (relation == null) {
|
|
|
- throw new BusinessRuntimeException(GROUP_INDEX_NOT_FIND.getCode(), GROUP_INDEX_NOT_FIND.getMsg());
|
|
|
- }
|
|
|
- if (relation.getUserId() != null && relation.getUserId() > 0L) {
|
|
|
- throw new BusinessRuntimeException(GROUP_INDEX_ALREADY_BE_USER.getCode(), GROUP_INDEX_ALREADY_BE_USER.getMsg());
|
|
|
- }
|
|
|
-
|
|
|
- } else {
|
|
|
- //TODO 如果没指定座位,等待逻辑确认
|
|
|
- GroupsTrips groups = groupsMapper.selectOne(Wrappers.lambdaQuery(GroupsTrips.class).eq(GroupsTrips::getSkuId, payRequest.getSkuId()).gt(GroupsTrips::getAvailableNum, 0).last("limit 1").orderByAsc(GroupsTrips::getAvailableNum));
|
|
|
- if (groups == null) {
|
|
|
- //新增车次
|
|
|
- groups = new GroupsTrips();
|
|
|
- groups.setSkuId(sku.getId());
|
|
|
- groups.setNum(sku.getNum());
|
|
|
- groups.setAvailableNum(sku.getNum());
|
|
|
- groups.setStatus(GroupsTrips.Status.waiting);
|
|
|
- groups.setRemark("等待设置账号");
|
|
|
- groupsMapper.insert(groups);
|
|
|
- relation = new GroupsRelation();
|
|
|
- relation.setGroupsId(groups.getId());
|
|
|
- relation.setNum(1);
|
|
|
- relation.setStatus(GroupsRelation.Status.locking);
|
|
|
- relation.setGroupsId(groups.getId());
|
|
|
- groupsRelationMapper.insert(relation);
|
|
|
-
|
|
|
- for (int i = 2; i <= groups.getNum(); i++) {
|
|
|
- GroupsRelation groupsRelation = new GroupsRelation();
|
|
|
- groupsRelation.setGroupsId(groups.getId());
|
|
|
- groupsRelation.setNum(i);
|
|
|
- groupsRelation.setStatus(GroupsRelation.Status.none);
|
|
|
- groupsRelationMapper.insert(groupsRelation);
|
|
|
- }
|
|
|
- } else {
|
|
|
- //寻找快满编车队进行占座
|
|
|
- relation = groupsRelationMapper.selectOne(Wrappers.lambdaQuery(GroupsRelation.class)
|
|
|
- .eq(GroupsRelation::getGroupsId, groups.getId())
|
|
|
- .eq(GroupsRelation::getStatus, "none")
|
|
|
- .eq(GroupsRelation::getUserId, 0)
|
|
|
- .orderByAsc(GroupsRelation::getNum)
|
|
|
- .last("limit 1")
|
|
|
- );
|
|
|
- if (relation == null) {
|
|
|
- throw new BusinessRuntimeException(GROUP_INDEX_NOT_FIND.getCode(), GROUP_INDEX_NOT_FIND.getMsg());
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- //锁定座位
|
|
|
- setRelation(relation.getId(), payRequest.getUserId());
|
|
|
- relation.setUserId(user.getId());
|
|
|
- relation.setStatus(GroupsRelation.Status.locking);
|
|
|
- groupsRelationMapper.updateById(relation);
|
|
|
- relationId = relation.getId();
|
|
|
- }else {
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- /* 生成订单 */
|
|
|
- String donNo = SEQUENCE.nextId().toString();
|
|
|
- OrderDon orderDon = new OrderDon();
|
|
|
- orderDon.setOrderNo(donNo);
|
|
|
- orderDon.setOpenId(payOpenId);
|
|
|
- orderDon.setMoney(payRequest.getDonMoney());
|
|
|
- orderDon.setSkuId(payRequest.getSkuId());
|
|
|
- orderDon.setRelationId(relationId);
|
|
|
- orderDon.setNum(payRequest.getNum());
|
|
|
- orderDon.setGoodsId(goodsDon.getId());
|
|
|
- orderDon.setStatus(OrderDon.Status.noPayment);
|
|
|
- orderDon.setUserId(user.getId());
|
|
|
- this.saveOrUpdate(orderDon);
|
|
|
-
|
|
|
-
|
|
|
- if (goodsDon.getType() == 2) {
|
|
|
- saveTransport(payRequest.getAddressId(), orderDon.getId());
|
|
|
- }
|
|
|
-
|
|
|
- jobManager.addJob(EXPIRY_TIME, () -> {
|
|
|
- closeOrder(orderDon.getId());
|
|
|
- });
|
|
|
-
|
|
|
- return orderDon;
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public H5JsPayParams pay(Long orderId) throws Exception {
|
|
|
- log.info("调起微信支付[start] orderId:{}", orderId);
|
|
|
- OrderDon orderDon = this.getById(orderId);
|
|
|
-
|
|
|
- OrderAttach attach = new OrderAttach();
|
|
|
- attach.setO(orderDon.getId());
|
|
|
-
|
|
|
- String toWechatAttach = Codec.DoBase64.custom()
|
|
|
- .setData(Jsons.toJson(attach)).encodeAsText();
|
|
|
-
|
|
|
- H5JsPayParams params = weChatService.getJsPayParams(
|
|
|
- weChatConfig.getAppid(),
|
|
|
- orderDon.getOpenId(),
|
|
|
- orderDon.getMoney().intValue(),
|
|
|
- orderDon.getOrderNo(),
|
|
|
- weChatConfig.getDomain() + "applets/order/prepay/notify",
|
|
|
- toWechatAttach,
|
|
|
- "银河录像局"
|
|
|
- );
|
|
|
-
|
|
|
- log.info("微信支付成功[end]");
|
|
|
- return params;
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- @Transactional(rollbackFor = Throwable.class)
|
|
|
- @Override
|
|
|
- public void prepayNotify(Map<String, String> map) throws Exception {
|
|
|
- /* 此处处理订单等业务逻辑 */
|
|
|
- // 获取订单 和 微信订单号 和 支付的金额
|
|
|
-
|
|
|
- String attach = Codec.DoBase64.custom().setData(map.get("attach")).decodeAsText();
|
|
|
-
|
|
|
- OrderAttach orderAttach = Jsons.parseObject(attach, OrderAttach.class);
|
|
|
-
|
|
|
- final Long oid = orderAttach.getO();
|
|
|
-
|
|
|
- //final Long shareId = orderAttach.getShared();
|
|
|
-
|
|
|
- OrderDon order = this.getById(oid);
|
|
|
-
|
|
|
- if (null == order) {
|
|
|
- throw BusinessRuntimeException.getInstance("订单不存在.");
|
|
|
- }
|
|
|
-
|
|
|
- // 校验签名
|
|
|
- boolean f = weChatService.checkSignWithMd5(map, weChatConfig.getShopKey());
|
|
|
- if (!f) {
|
|
|
- log.error("回调数据:{}", map);
|
|
|
- throw BusinessRuntimeException.getInstance("支付成功回调, 校验签名失败.");
|
|
|
- }
|
|
|
-
|
|
|
- GoodsDonSku sku = goodsDonSkuMapper.selectById(order.getSkuId());
|
|
|
- GoodsDon goodsDon = goodsDonMapper.selectById(sku.getGoodsId());
|
|
|
-
|
|
|
- String transactionId = map.get("transaction_id");
|
|
|
-
|
|
|
- if (order.getStatus().equals(OrderDon.Status.hasPayment)) {
|
|
|
- log.info("已回调,重复修改状态 id:{}", order.getId());
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- // 更改订单状态
|
|
|
- order.setTransactionId(transactionId);
|
|
|
- order.setStatus(goodsDon.getType() == 1 && goodsDon.getSecondType() == 2 ? OrderDon.Status.complete : OrderDon.Status.hasPayment);
|
|
|
-
|
|
|
- order.setPayTime(DateUtil.parse(map.get("time_end"), "yyyyMMddHHmmss"));
|
|
|
-
|
|
|
- if (StringUtils.isBlank(order.getOpenId())) {
|
|
|
- order.setOpenId(map.get("openid"));
|
|
|
- }
|
|
|
-
|
|
|
- if (goodsDon.getType() == 1) {
|
|
|
- //修改车位状态
|
|
|
- GroupsRelation relation = groupsRelationMapper.selectById(order.getRelationId());
|
|
|
- GroupsTrips groupsTrips = groupsMapper.selectById(relation.getGroupsId());
|
|
|
- if (GroupsRelation.Status.locking.equals(relation.getStatus()) || GroupsRelation.Status.validity.equals(relation.getStatus())) {
|
|
|
- relation.setStatus(GroupsRelation.Status.validity);
|
|
|
- //续费后,下一次续费意愿状态为false
|
|
|
- relation.setRenewStatus(false);
|
|
|
- relation.setIsHandle(false);
|
|
|
- if (GroupsTrips.Status.validity.equals(groupsTrips.getStatus())) {
|
|
|
- //如果续费增加时间,如果首次则设置当前时间为初始时间
|
|
|
- Date expiryTime = Optional.ofNullable(relation.getExpiryTime()).orElse(new Date());
|
|
|
- GoodsDonSku donSku = goodsDonSkuMapper.selectById(order.getSkuId());
|
|
|
-
|
|
|
- Date newDate = DateUtil.offset(expiryTime, DateField.MONTH, donSku.getMonths() * order.getNum());
|
|
|
- relation.setExpiryTime(newDate);
|
|
|
- relation.setStartTime(relation.getStartTime() == null ? new Date() : null);
|
|
|
- }else if(GroupsTrips.Status.waiting.equals(groupsTrips.getStatus())){
|
|
|
- order.setStatus(OrderDon.Status.hasPayment);
|
|
|
- }
|
|
|
- //TODO 如未发车逻辑
|
|
|
- groupsRelationMapper.updateById(relation);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- this.updateById(order);
|
|
|
-
|
|
|
- //新订单产生 发送模板消息给用户、客服
|
|
|
- User user = userMapper.selectById(order.getUserId());
|
|
|
- THREAD_POOL_TASK_EXECUTOR.execute(() -> {
|
|
|
- try {
|
|
|
- //发送至用户消息
|
|
|
- newOderSendMsgByType(order, goodsDon, sku, user, user.getOpenId());
|
|
|
- } catch (Exception e) {
|
|
|
- log.error("向用户发送新订单{}通知消息失败:{}", order.getOrderNo(), e);
|
|
|
- }
|
|
|
- });
|
|
|
- THREAD_POOL_TASK_EXECUTOR.execute(() -> {
|
|
|
- try {
|
|
|
- //发送至客服消息
|
|
|
- List<CustomerService> customerServices = customerServiceMapper.selectList(null);
|
|
|
- for (CustomerService customerService : customerServices) {
|
|
|
- log.info("向客服{}发送新订单消息通知..", customerService.getNickName());
|
|
|
- newOderSendMsgByType(order, goodsDon, sku, user, customerService.getOpenId());
|
|
|
- }
|
|
|
- } catch (Exception e) {
|
|
|
- log.error("向客服发送新订单{}通知消息失败:{}", order.getOrderNo(), e);
|
|
|
- }
|
|
|
- });
|
|
|
- }
|
|
|
-
|
|
|
- private void newOderSendMsgByType(OrderDon order, GoodsDon goodsDon, GoodsDonSku sku, User user, String toPeople) throws Exception {
|
|
|
- TemplateEnum templateEnum = null;
|
|
|
- if (EnvCommonService.active.equals(envCommonService.getEnv())) {
|
|
|
- templateEnum = TemplateEnum.NEW_ORDER_ENV_TEMPLATE;
|
|
|
- }else {
|
|
|
- templateEnum = TemplateEnum.NEW_ORDER_PRD_TEMPLATE;
|
|
|
- }
|
|
|
- WxMpTemplateMessage templateMessage = new WxMpTemplateMessage()
|
|
|
- .setToUser(toPeople)
|
|
|
- .setTemplateId(templateEnum.getTemplateId())
|
|
|
- //TODO
|
|
|
- .setUrl(" ");
|
|
|
- WxMpTemplateMessage.TemplateData data = templateMessage.getData();
|
|
|
- data.setFirst(new WxMpTemplateData("新订单通知!"));
|
|
|
- data.setKeyword1(new WxMpTemplateData(order.getOrderNo()));
|
|
|
- data.setKeyword2(new WxMpTemplateData(String.format("%s,%s", goodsDon.getTitle(), sku.getSpecVal())));
|
|
|
- data.setKeyword3(new WxMpTemplateData(user.getNickname()));
|
|
|
- data.setKeyword4(new WxMpTemplateData(order.getMoney().divide(BigDecimal.valueOf(100)).toString()));
|
|
|
- data.setKeyword5(new WxMpTemplateData(DateUtil.format(order.getCreatedTime(), "yyyy-MM-dd HH:mm:ss")));
|
|
|
- data.setRemark(new WxMpTemplateData("点击查看详情"));
|
|
|
- weChatService.sendTemplateMessage(weChatService.getAccessToken(), Jsons.toJson(templateMessage));
|
|
|
- }
|
|
|
-
|
|
|
- @Transactional(rollbackFor = Throwable.class)
|
|
|
- @Override
|
|
|
- public void closeOrder(Long orderId) {
|
|
|
- log.info("关闭订单 orderId:{}", orderId);
|
|
|
- //关闭订单逻辑
|
|
|
- OrderDon orderDon = getById(orderId);
|
|
|
- if (OrderDon.Status.noPayment.equals(orderDon.getStatus())) {
|
|
|
- //查询微信支付是否已支付
|
|
|
- orderDon.setStatus(OrderDon.Status.close);
|
|
|
- updateById(orderDon);
|
|
|
-
|
|
|
- //关闭车位锁定
|
|
|
- GroupsRelation groupsRelation = groupsRelationMapper.selectById(orderDon.getRelationId());
|
|
|
- if (groupsRelation != null) {
|
|
|
- if (!groupsRelation.getUserId().equals(orderDon.getUserId())) {
|
|
|
- throw new BusinessRuntimeException("订单用户与车位用户不匹配!");
|
|
|
- } else {
|
|
|
- if (GroupsRelation.Status.locking.equals(groupsRelation.getStatus())) {
|
|
|
- groupsRelation.setUserId(0L);
|
|
|
- groupsRelation.setStatus(GroupsRelation.Status.none);
|
|
|
- groupsRelationMapper.updateById(groupsRelation);
|
|
|
- delRelation(groupsRelation.getId());
|
|
|
-
|
|
|
- //车位空余发送模板消息
|
|
|
- TASK_POOL.execute(() -> {
|
|
|
- try {
|
|
|
- List<CustomerService> customerServices = customerServiceMapper.selectList(null);
|
|
|
- for (CustomerService customerService : customerServices) {
|
|
|
- log.info("发送客服{}空车位通知消息", customerService.getNickName());
|
|
|
- emptySendMsgNotify(orderDon, customerService.getOpenId());
|
|
|
- }
|
|
|
- } catch (Exception e) {
|
|
|
- log.error("发送{}空车位模板消息至客服失败:{}", orderDon.getGoodsId(), e);
|
|
|
- }
|
|
|
- });
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- private void emptySendMsgNotify(OrderDon orderDon, String toPeople) throws Exception {
|
|
|
- TemplateEnum templateEnum = null;
|
|
|
- if (EnvCommonService.active.equals(envCommonService.getEnv())) {
|
|
|
- templateEnum = TemplateEnum.EMPTY_ENV_TEMPLATE;
|
|
|
- }else {
|
|
|
- templateEnum = TemplateEnum.EMPTY_PRD_TEMPLATE;
|
|
|
- }
|
|
|
- User u = userMapper.selectById(orderDon.getUserId());
|
|
|
- WxMpTemplateMessage templateMessage = new WxMpTemplateMessage()
|
|
|
- .setToUser(toPeople)
|
|
|
- .setTemplateId(templateEnum.getTemplateId())
|
|
|
- //TODO
|
|
|
- .setUrl(" ");
|
|
|
- GoodsDon goodsDon = goodsDonMapper.selectById(orderDon.getGoodsId());
|
|
|
- GoodsDonSku goodsDonSku = goodsDonSkuMapper.selectById(orderDon.getSkuId());
|
|
|
- WxMpTemplateMessage.TemplateData data = templateMessage.getData();
|
|
|
- data.setFirst(new WxMpTemplateData("空车位通知!"));
|
|
|
- data.setKeyword1(new WxMpTemplateData(orderDon.getOrderNo()));
|
|
|
- data.setKeyword2(new WxMpTemplateData(String.format("%s,%s", goodsDon.getTitle(), goodsDonSku.getSpecVal())));
|
|
|
- data.setKeyword3(new WxMpTemplateData((u == null ? " " : u.getNickname())));
|
|
|
- data.setKeyword4(new WxMpTemplateData(orderDon.getMoney().divide(BigDecimal.valueOf(100)).toString()));
|
|
|
- data.setKeyword5(new WxMpTemplateData(DateUtil.format(orderDon.getCreatedTime(), "yyyy-MM-dd HH:mm:ss")));
|
|
|
- data.setRemark(new WxMpTemplateData("请尽快关联账号信息"));
|
|
|
- weChatService.sendTemplateMessage(weChatService.getAccessToken(), Jsons.toJson(templateMessage));
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public OrderDon renewal(OrderPayRequest payRequest) {
|
|
|
- User user = userMapper.selectById(payRequest.getUserId());
|
|
|
-
|
|
|
- Long relationId = payRequest.getRelationId();
|
|
|
- if (relationId == null || relationId <= 0 || payRequest.getSkuId() == null || payRequest.getNum() == null) {
|
|
|
- throw new BusinessRuntimeException("缺少必填参数");
|
|
|
- }
|
|
|
-
|
|
|
- GoodsDonSku sku = goodsDonSkuMapper.selectById(payRequest.getSkuId());
|
|
|
-
|
|
|
- GroupsRelation relation = groupsRelationMapper.selectById(relationId);
|
|
|
- if (relation == null) {
|
|
|
- throw new BusinessRuntimeException("");
|
|
|
- }
|
|
|
- if (!relation.getUserId().equals(user.getId())) {
|
|
|
- throw new BusinessRuntimeException("");
|
|
|
- }
|
|
|
-
|
|
|
- GoodsDon goodsDon = goodsDonMapper.selectById(sku.getGoodsId());
|
|
|
- if (goodsDon == null || !goodsDon.getStatus()) {
|
|
|
- throw new BusinessRuntimeException("商品已下架");
|
|
|
- }
|
|
|
-
|
|
|
- if (goodsDon.getType() == 2) {
|
|
|
- throw new BusinessRuntimeException("实物不支持续费");
|
|
|
- }
|
|
|
-
|
|
|
- String payOpenId = user.getOpenId();
|
|
|
-
|
|
|
- /* 生成订单 */
|
|
|
- String donNo = SEQUENCE.nextId().toString();
|
|
|
- OrderDon orderDon = new OrderDon();
|
|
|
- orderDon.setOrderNo(donNo);
|
|
|
- orderDon.setOpenId(payOpenId);
|
|
|
- orderDon.setMoney(sku.getPrice().multiply(BigDecimal.valueOf(payRequest.getNum())));
|
|
|
- orderDon.setSkuId(payRequest.getSkuId());
|
|
|
- orderDon.setRelationId(relation.getId());
|
|
|
-
|
|
|
- orderDon.setStatus(OrderDon.Status.noPayment);
|
|
|
- orderDon.setUserId(user.getId());
|
|
|
- this.saveOrUpdate(orderDon);
|
|
|
-
|
|
|
- jobManager.addJob(EXPIRY_TIME, () -> {
|
|
|
- closeOrder(orderDon.getId());
|
|
|
- });
|
|
|
-
|
|
|
- return orderDon;
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public OrderDonView getDetail(Long orderId, long userId) {
|
|
|
-
|
|
|
- OrderDonView detail = beanSearcher.searchFirst(OrderDonView.class, MapUtils.builder()
|
|
|
- .field(OrderDonView::getUserId,userId)
|
|
|
- .field(OrderDonView::getId,orderId)
|
|
|
- .orderBy(OrderDonView::getId).desc()
|
|
|
- .build());
|
|
|
-
|
|
|
- detail.setTransport(transportMapper.selectOne(Wrappers.lambdaQuery(OrderDonTransport.class).eq(OrderDonTransport::getOrderId,detail.getId()).last(" limit 1")));
|
|
|
- detail.setWaybill(waybillMapper.selectOne(Wrappers.lambdaQuery(OrderDonWaybill.class).eq(OrderDonWaybill::getOrderId,detail.getId()).last(" limit 1")));
|
|
|
- return detail;
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public List<OrderDon> getAppleOneOrderDons(String appleOne, List<Long> skuIds, List<String> noOrderStatus, Date yesZeroDate, Date thisZeroDate) {
|
|
|
- return orderDonMapper.getAppleOneOrderDons(appleOne, skuIds, noOrderStatus, yesZeroDate, thisZeroDate);
|
|
|
- }
|
|
|
-
|
|
|
- public void setRelation(Long relationId, Long userId) {
|
|
|
- int noPayCount = count(Wrappers.lambdaQuery(OrderDon.class).eq(OrderDon::getUserId, userId).eq(OrderDon::getStatus, OrderDon.Status.noPayment.toString()));
|
|
|
-
|
|
|
- if (noPayCount > 0) {
|
|
|
- throw new BusinessRuntimeException("您有未支付订单.");
|
|
|
- }
|
|
|
-
|
|
|
- if (redisService.get(RedisKey.GROUPS_RELATION_NUM_KEY + relationId) != null) {
|
|
|
- throw new BusinessRuntimeException("客官手慢啦,该座位已经有人啦!");
|
|
|
- } else {
|
|
|
- redisService.set(RedisKey.GROUPS_RELATION_NUM_KEY + relationId, userId, 60 * 5L);
|
|
|
- GroupsRelation relation = groupsRelationMapper.selectById(relationId);
|
|
|
- int count = groupsMapper.decrAvailableNum(relation.getGroupsId());
|
|
|
- if (count == 0) {
|
|
|
- log.error("车位异常 groupId:{}", relation.getGroupsId());
|
|
|
- throw new BusinessRuntimeException("车位异常");
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- public void delRelation(Long relationId) {
|
|
|
- redisService.del(RedisKey.GROUPS_RELATION_NUM_KEY + relationId);
|
|
|
- GroupsRelation relation = groupsRelationMapper.selectById(relationId);
|
|
|
- int count = groupsMapper.incrAvailableNum(relation.getGroupsId());
|
|
|
- if (count == 0) {
|
|
|
- log.error("车位异常 groupId:{}", relation.getGroupsId());
|
|
|
- throw new BusinessRuntimeException("车位异常");
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- public void saveTransport(Long addressId, Long orderId) {
|
|
|
- if (addressId == null) {
|
|
|
- throw new BusinessRuntimeException("请选择收货地址.");
|
|
|
- }
|
|
|
- Address address = addressMapper.selectById(addressId);
|
|
|
- if (address == null) {
|
|
|
- throw new BusinessRuntimeException("请添加收货地址.");
|
|
|
- }
|
|
|
- OrderDonTransport transport = new OrderDonTransport();
|
|
|
- transport.setOrderId(orderId);
|
|
|
- transport.setReceiver(address.getReceiver());
|
|
|
- transport.setPhone(address.getPhone());
|
|
|
- transport.setProvince(address.getProvince());
|
|
|
- transport.setCity(address.getCity());
|
|
|
- transport.setDistrict(address.getDistrict());
|
|
|
- transport.setAddress(address.getAddress());
|
|
|
- orderDonTransportMapper.insert(transport);
|
|
|
- }
|
|
|
+ private final WeChatService weChatService;
|
|
|
+
|
|
|
+ private final RedisService redisService;
|
|
|
+
|
|
|
+ private final GoodsDonSkuMapper goodsDonSkuMapper;
|
|
|
+
|
|
|
+ private final GoodsDonMapper goodsDonMapper;
|
|
|
+
|
|
|
+ private final GroupsRelationMapper groupsRelationMapper;
|
|
|
+
|
|
|
+ private final BeanSearcher beanSearcher;
|
|
|
+
|
|
|
+ private final GroupsMapper groupsMapper;
|
|
|
+
|
|
|
+ private final JobManager jobManager;
|
|
|
+
|
|
|
+ private final OrderDonTransportMapper orderDonTransportMapper;
|
|
|
+
|
|
|
+ private final AddressMapper addressMapper;
|
|
|
+
|
|
|
+ private final OrderDonTransportMapper transportMapper;
|
|
|
+
|
|
|
+ private final OrderDonWaybillMapper waybillMapper;
|
|
|
+
|
|
|
+ private final OrderDonMapper orderDonMapper;
|
|
|
+
|
|
|
+ private final EnvCommonService envCommonService;
|
|
|
+
|
|
|
+ private static final GlobalThreadPoolTaskExecutor TASK_POOL = GlobalThreadPoolTaskExecutor.getInstance();
|
|
|
+
|
|
|
+ private final CustomerServiceMapper customerServiceMapper;
|
|
|
+
|
|
|
+
|
|
|
+ @Transactional(rollbackFor = Throwable.class)
|
|
|
+ @Override
|
|
|
+ public OrderDon submit(OrderPayRequest payRequest) {
|
|
|
+ User user = userMapper.selectById(payRequest.getUserId());
|
|
|
+ GoodsDonSku sku = goodsDonSkuMapper.selectById(payRequest.getSkuId());
|
|
|
+ GoodsDon goodsDon = goodsDonMapper.selectById(sku.getGoodsId());
|
|
|
+ if (goodsDon == null || !goodsDon.getStatus()) {
|
|
|
+ throw new BusinessRuntimeException("商品已下架");
|
|
|
+ }
|
|
|
+ String payOpenId = user.getOpenId();
|
|
|
+
|
|
|
+ Long relationId = 0L;
|
|
|
+
|
|
|
+ if (goodsDon.getType() == 1) {
|
|
|
+ GroupsRelation relation = null;
|
|
|
+ //锁定座位
|
|
|
+ if (payRequest.getRelationId() != null && payRequest.getRelationId() > 0) {
|
|
|
+ relation = groupsRelationMapper.selectById(payRequest.getRelationId());
|
|
|
+ if (relation == null) {
|
|
|
+ throw new BusinessRuntimeException(GROUP_INDEX_NOT_FIND.getCode(), GROUP_INDEX_NOT_FIND.getMsg());
|
|
|
+ }
|
|
|
+ if (relation.getUserId() != null && relation.getUserId() > 0L) {
|
|
|
+ throw new BusinessRuntimeException(GROUP_INDEX_ALREADY_BE_USER.getCode(), GROUP_INDEX_ALREADY_BE_USER.getMsg());
|
|
|
+ }
|
|
|
+
|
|
|
+ } else {
|
|
|
+ //TODO 如果没指定座位,等待逻辑确认
|
|
|
+ GroupsTrips groups = groupsMapper.selectOne(Wrappers.lambdaQuery(GroupsTrips.class).eq(GroupsTrips::getSkuId, payRequest.getSkuId()).gt(GroupsTrips::getAvailableNum, 0).last("limit 1").orderByAsc(GroupsTrips::getAvailableNum));
|
|
|
+ if (groups == null) {
|
|
|
+ //新增车次
|
|
|
+ groups = new GroupsTrips();
|
|
|
+ groups.setSkuId(sku.getId());
|
|
|
+ groups.setNum(sku.getNum());
|
|
|
+ groups.setAvailableNum(sku.getNum());
|
|
|
+ groups.setStatus(GroupsTrips.Status.waiting);
|
|
|
+ groups.setRemark("等待设置账号");
|
|
|
+ groupsMapper.insert(groups);
|
|
|
+ relation = new GroupsRelation();
|
|
|
+ relation.setGroupsId(groups.getId());
|
|
|
+ relation.setNum(1);
|
|
|
+ relation.setStatus(GroupsRelation.Status.locking);
|
|
|
+ relation.setGroupsId(groups.getId());
|
|
|
+ groupsRelationMapper.insert(relation);
|
|
|
+
|
|
|
+ for (int i = 2; i <= groups.getNum(); i++) {
|
|
|
+ GroupsRelation groupsRelation = new GroupsRelation();
|
|
|
+ groupsRelation.setGroupsId(groups.getId());
|
|
|
+ groupsRelation.setNum(i);
|
|
|
+ groupsRelation.setStatus(GroupsRelation.Status.none);
|
|
|
+ groupsRelationMapper.insert(groupsRelation);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ //寻找快满编车队进行占座
|
|
|
+ relation = groupsRelationMapper.selectOne(Wrappers.lambdaQuery(GroupsRelation.class)
|
|
|
+ .eq(GroupsRelation::getGroupsId, groups.getId())
|
|
|
+ .eq(GroupsRelation::getStatus, "none")
|
|
|
+ .eq(GroupsRelation::getUserId, 0)
|
|
|
+ .orderByAsc(GroupsRelation::getNum)
|
|
|
+ .last("limit 1")
|
|
|
+ );
|
|
|
+ if (relation == null) {
|
|
|
+ throw new BusinessRuntimeException(GROUP_INDEX_NOT_FIND.getCode(), GROUP_INDEX_NOT_FIND.getMsg());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ //锁定座位
|
|
|
+ setRelation(relation.getId(), payRequest.getUserId());
|
|
|
+ relation.setUserId(user.getId());
|
|
|
+ relation.setStatus(GroupsRelation.Status.locking);
|
|
|
+ groupsRelationMapper.updateById(relation);
|
|
|
+ relationId = relation.getId();
|
|
|
+ } else {
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ /* 生成订单 */
|
|
|
+ String donNo = SEQUENCE.nextId().toString();
|
|
|
+ OrderDon orderDon = new OrderDon();
|
|
|
+ orderDon.setOrderNo(donNo);
|
|
|
+ orderDon.setOpenId(payOpenId);
|
|
|
+ orderDon.setMoney(payRequest.getDonMoney());
|
|
|
+ orderDon.setSkuId(payRequest.getSkuId());
|
|
|
+ orderDon.setRelationId(relationId);
|
|
|
+ orderDon.setNum(payRequest.getNum());
|
|
|
+ orderDon.setGoodsId(goodsDon.getId());
|
|
|
+ orderDon.setStatus(OrderDon.Status.noPayment);
|
|
|
+ orderDon.setUserId(user.getId());
|
|
|
+ orderDon.setType(OrderDon.Type.getType(payRequest.getType()));
|
|
|
+ this.saveOrUpdate(orderDon);
|
|
|
+
|
|
|
+
|
|
|
+ if (goodsDon.getType() == 2) {
|
|
|
+ saveTransport(payRequest.getAddressId(), orderDon.getId());
|
|
|
+ }
|
|
|
+
|
|
|
+ jobManager.addJob(EXPIRY_TIME, () -> {
|
|
|
+ closeOrder(orderDon.getId());
|
|
|
+ });
|
|
|
+
|
|
|
+ return orderDon;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public H5JsPayParams pay(Long orderId, String tradeType) throws Exception {
|
|
|
+ log.info("调起微信支付[start] orderId:{}", orderId);
|
|
|
+ OrderDon orderDon = this.getById(orderId);
|
|
|
+
|
|
|
+ OrderAttach attach = new OrderAttach();
|
|
|
+ attach.setO(orderDon.getId());
|
|
|
+
|
|
|
+ String toWechatAttach = Codec.DoBase64.custom()
|
|
|
+ .setData(Jsons.toJson(attach)).encodeAsText();
|
|
|
+
|
|
|
+ H5JsPayParams params = weChatService.getJsPayParams(
|
|
|
+ weChatConfig.getAppid(),
|
|
|
+ orderDon.getOpenId(),
|
|
|
+ orderDon.getMoney().intValue(),
|
|
|
+ orderDon.getOrderNo(),
|
|
|
+ weChatConfig.getDomain() + "applets/order/prepay/notify",
|
|
|
+ toWechatAttach,
|
|
|
+ "银河录像局",
|
|
|
+ tradeType
|
|
|
+ );
|
|
|
+
|
|
|
+ log.info("微信支付成功[end]");
|
|
|
+ return params;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public H5JsPayParams wxPcWebPay(Long orderId, String tradeType) throws Exception {
|
|
|
+ log.info("调起微信支付[start] orderId:{}", orderId);
|
|
|
+ OrderDon orderDon = this.getById(orderId);
|
|
|
+
|
|
|
+ OrderAttach attach = new OrderAttach();
|
|
|
+ attach.setO(orderDon.getId());
|
|
|
+
|
|
|
+ String toWechatAttach = Codec.DoBase64.custom()
|
|
|
+ .setData(Jsons.toJson(attach)).encodeAsText();
|
|
|
+
|
|
|
+ H5JsPayParams params = weChatService.getJsPayParams(
|
|
|
+ weChatConfig.getAppid(),
|
|
|
+ orderDon.getOpenId(),
|
|
|
+ orderDon.getMoney().intValue(),
|
|
|
+ orderDon.getOrderNo(),
|
|
|
+ weChatConfig.getDomain() + "applets/order/pc/prepay/notify",
|
|
|
+ toWechatAttach,
|
|
|
+ "银河录像局",
|
|
|
+ tradeType
|
|
|
+ );
|
|
|
+
|
|
|
+ log.info("微信支付成功[end]");
|
|
|
+ return params;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ @Transactional(rollbackFor = Throwable.class)
|
|
|
+ @Override
|
|
|
+ public void prepayNotify(Map<String, String> map) throws Exception {
|
|
|
+ /* 此处处理订单等业务逻辑 */
|
|
|
+ // 获取订单 和 微信订单号 和 支付的金额
|
|
|
+
|
|
|
+ String attach = Codec.DoBase64.custom().setData(map.get("attach")).decodeAsText();
|
|
|
+
|
|
|
+ OrderAttach orderAttach = Jsons.parseObject(attach, OrderAttach.class);
|
|
|
+
|
|
|
+ final Long oid = orderAttach.getO();
|
|
|
+
|
|
|
+ //final Long shareId = orderAttach.getShared();
|
|
|
+
|
|
|
+ OrderDon order = this.getById(oid);
|
|
|
+
|
|
|
+ if (null == order) {
|
|
|
+ throw BusinessRuntimeException.getInstance("订单不存在.");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 校验签名
|
|
|
+ boolean f = weChatService.checkSignWithMd5(map, weChatConfig.getShopKey());
|
|
|
+ if (!f) {
|
|
|
+ log.error("回调数据:{}", map);
|
|
|
+ throw BusinessRuntimeException.getInstance("支付成功回调, 校验签名失败.");
|
|
|
+ }
|
|
|
+
|
|
|
+ GoodsDonSku sku = goodsDonSkuMapper.selectById(order.getSkuId());
|
|
|
+ GoodsDon goodsDon = goodsDonMapper.selectById(sku.getGoodsId());
|
|
|
+
|
|
|
+ String transactionId = map.get("transaction_id");
|
|
|
+
|
|
|
+ if (order.getStatus().equals(OrderDon.Status.hasPayment)) {
|
|
|
+ log.info("已回调,重复修改状态 id:{}", order.getId());
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 更改订单状态
|
|
|
+ order.setTransactionId(transactionId);
|
|
|
+ order.setStatus(goodsDon.getType() == 1 && goodsDon.getSecondType() == 2 ? OrderDon.Status.complete : OrderDon.Status.hasPayment);
|
|
|
+
|
|
|
+ order.setPayTime(DateUtil.parse(map.get("time_end"), "yyyyMMddHHmmss"));
|
|
|
+
|
|
|
+ if (StringUtils.isBlank(order.getOpenId())) {
|
|
|
+ order.setOpenId(map.get("openid"));
|
|
|
+ }
|
|
|
+ updateCarParkAndSendMsg(goodsDon, sku, order);
|
|
|
+ order.setType(OrderDon.Type.WeChat);
|
|
|
+ this.updateById(order);
|
|
|
+ }
|
|
|
+
|
|
|
+ private void newOderSendMsgByType(OrderDon order, GoodsDon goodsDon, GoodsDonSku sku, User user, String toPeople) throws Exception {
|
|
|
+ TemplateEnum templateEnum = null;
|
|
|
+ if (EnvCommonService.active.equals(envCommonService.getEnv())) {
|
|
|
+ templateEnum = TemplateEnum.NEW_ORDER_ENV_TEMPLATE;
|
|
|
+ } else {
|
|
|
+ templateEnum = TemplateEnum.NEW_ORDER_PRD_TEMPLATE;
|
|
|
+ }
|
|
|
+ WxMpTemplateMessage templateMessage = new WxMpTemplateMessage()
|
|
|
+ .setToUser(toPeople)
|
|
|
+ .setTemplateId(templateEnum.getTemplateId())
|
|
|
+ //TODO
|
|
|
+ .setUrl(" ");
|
|
|
+ WxMpTemplateMessage.TemplateData data = templateMessage.getData();
|
|
|
+ data.setFirst(new WxMpTemplateData("新订单通知!"));
|
|
|
+ data.setKeyword1(new WxMpTemplateData(order.getOrderNo()));
|
|
|
+ data.setKeyword2(new WxMpTemplateData(String.format("%s,%s", goodsDon.getTitle(), sku.getSpecVal())));
|
|
|
+ data.setKeyword3(new WxMpTemplateData(user.getNickname()));
|
|
|
+ data.setKeyword4(new WxMpTemplateData(order.getMoney().divide(BigDecimal.valueOf(100)).toString()));
|
|
|
+ data.setKeyword5(new WxMpTemplateData(DateUtil.format(order.getCreatedTime(), "yyyy-MM-dd HH:mm:ss")));
|
|
|
+ data.setRemark(new WxMpTemplateData("点击查看详情"));
|
|
|
+ weChatService.sendTemplateMessage(weChatService.getAccessToken(), Jsons.toJson(templateMessage));
|
|
|
+ }
|
|
|
+
|
|
|
+ @Transactional(rollbackFor = Throwable.class)
|
|
|
+ @Override
|
|
|
+ public void closeOrder(Long orderId) {
|
|
|
+ log.info("关闭订单 orderId:{}", orderId);
|
|
|
+ //关闭订单逻辑
|
|
|
+ OrderDon orderDon = getById(orderId);
|
|
|
+ if (OrderDon.Status.noPayment.equals(orderDon.getStatus())) {
|
|
|
+ //查询微信支付是否已支付
|
|
|
+ orderDon.setStatus(OrderDon.Status.close);
|
|
|
+ updateById(orderDon);
|
|
|
+
|
|
|
+ //关闭车位锁定
|
|
|
+ GroupsRelation groupsRelation = groupsRelationMapper.selectById(orderDon.getRelationId());
|
|
|
+ if (groupsRelation != null) {
|
|
|
+ if (!groupsRelation.getUserId().equals(orderDon.getUserId())) {
|
|
|
+ throw new BusinessRuntimeException("订单用户与车位用户不匹配!");
|
|
|
+ } else {
|
|
|
+ if (GroupsRelation.Status.locking.equals(groupsRelation.getStatus())) {
|
|
|
+ groupsRelation.setUserId(0L);
|
|
|
+ groupsRelation.setStatus(GroupsRelation.Status.none);
|
|
|
+ groupsRelationMapper.updateById(groupsRelation);
|
|
|
+ delRelation(groupsRelation.getId());
|
|
|
+
|
|
|
+ //车位空余发送模板消息
|
|
|
+ TASK_POOL.execute(() -> {
|
|
|
+ try {
|
|
|
+ List<CustomerService> customerServices = customerServiceMapper.selectList(null);
|
|
|
+ for (CustomerService customerService : customerServices) {
|
|
|
+ log.info("发送客服{}空车位通知消息", customerService.getNickName());
|
|
|
+ emptySendMsgNotify(orderDon, customerService.getOpenId());
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("发送{}空车位模板消息至客服失败:{}", orderDon.getGoodsId(), e);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void emptySendMsgNotify(OrderDon orderDon, String toPeople) throws Exception {
|
|
|
+ TemplateEnum templateEnum = null;
|
|
|
+ if (EnvCommonService.active.equals(envCommonService.getEnv())) {
|
|
|
+ templateEnum = TemplateEnum.EMPTY_ENV_TEMPLATE;
|
|
|
+ } else {
|
|
|
+ templateEnum = TemplateEnum.EMPTY_PRD_TEMPLATE;
|
|
|
+ }
|
|
|
+ User u = userMapper.selectById(orderDon.getUserId());
|
|
|
+ WxMpTemplateMessage templateMessage = new WxMpTemplateMessage()
|
|
|
+ .setToUser(toPeople)
|
|
|
+ .setTemplateId(templateEnum.getTemplateId())
|
|
|
+ //TODO
|
|
|
+ .setUrl(" ");
|
|
|
+ GoodsDon goodsDon = goodsDonMapper.selectById(orderDon.getGoodsId());
|
|
|
+ GoodsDonSku goodsDonSku = goodsDonSkuMapper.selectById(orderDon.getSkuId());
|
|
|
+ WxMpTemplateMessage.TemplateData data = templateMessage.getData();
|
|
|
+ data.setFirst(new WxMpTemplateData("空车位通知!"));
|
|
|
+ data.setKeyword1(new WxMpTemplateData(orderDon.getOrderNo()));
|
|
|
+ data.setKeyword2(new WxMpTemplateData(String.format("%s,%s", goodsDon.getTitle(), goodsDonSku.getSpecVal())));
|
|
|
+ data.setKeyword3(new WxMpTemplateData((u == null ? " " : u.getNickname())));
|
|
|
+ data.setKeyword4(new WxMpTemplateData(orderDon.getMoney().divide(BigDecimal.valueOf(100)).toString()));
|
|
|
+ data.setKeyword5(new WxMpTemplateData(DateUtil.format(orderDon.getCreatedTime(), "yyyy-MM-dd HH:mm:ss")));
|
|
|
+ data.setRemark(new WxMpTemplateData("请尽快关联账号信息"));
|
|
|
+ weChatService.sendTemplateMessage(weChatService.getAccessToken(), Jsons.toJson(templateMessage));
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public OrderDon renewal(OrderPayRequest payRequest) {
|
|
|
+ User user = userMapper.selectById(payRequest.getUserId());
|
|
|
+
|
|
|
+ Long relationId = payRequest.getRelationId();
|
|
|
+ if (relationId == null || relationId <= 0 || payRequest.getSkuId() == null || payRequest.getNum() == null) {
|
|
|
+ throw new BusinessRuntimeException("缺少必填参数");
|
|
|
+ }
|
|
|
+
|
|
|
+ GoodsDonSku sku = goodsDonSkuMapper.selectById(payRequest.getSkuId());
|
|
|
+
|
|
|
+ GroupsRelation relation = groupsRelationMapper.selectById(relationId);
|
|
|
+ if (relation == null) {
|
|
|
+ throw new BusinessRuntimeException("");
|
|
|
+ }
|
|
|
+ if (!relation.getUserId().equals(user.getId())) {
|
|
|
+ throw new BusinessRuntimeException("");
|
|
|
+ }
|
|
|
+
|
|
|
+ GoodsDon goodsDon = goodsDonMapper.selectById(sku.getGoodsId());
|
|
|
+ if (goodsDon == null || !goodsDon.getStatus()) {
|
|
|
+ throw new BusinessRuntimeException("商品已下架");
|
|
|
+ }
|
|
|
+
|
|
|
+ if (goodsDon.getType() == 2) {
|
|
|
+ throw new BusinessRuntimeException("实物不支持续费");
|
|
|
+ }
|
|
|
+
|
|
|
+ String payOpenId = user.getOpenId();
|
|
|
+
|
|
|
+ /* 生成订单 */
|
|
|
+ String donNo = SEQUENCE.nextId().toString();
|
|
|
+ OrderDon orderDon = new OrderDon();
|
|
|
+ orderDon.setOrderNo(donNo);
|
|
|
+ orderDon.setOpenId(payOpenId);
|
|
|
+ orderDon.setMoney(sku.getPrice().multiply(BigDecimal.valueOf(payRequest.getNum())));
|
|
|
+ orderDon.setSkuId(payRequest.getSkuId());
|
|
|
+ orderDon.setRelationId(relation.getId());
|
|
|
+
|
|
|
+ orderDon.setStatus(OrderDon.Status.noPayment);
|
|
|
+ orderDon.setUserId(user.getId());
|
|
|
+ this.saveOrUpdate(orderDon);
|
|
|
+
|
|
|
+ jobManager.addJob(EXPIRY_TIME, () -> {
|
|
|
+ closeOrder(orderDon.getId());
|
|
|
+ });
|
|
|
+
|
|
|
+ return orderDon;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public OrderDonView getDetail(Long orderId, long userId) {
|
|
|
+
|
|
|
+ OrderDonView detail = beanSearcher.searchFirst(OrderDonView.class, MapUtils.builder()
|
|
|
+ .field(OrderDonView::getUserId, userId)
|
|
|
+ .field(OrderDonView::getId, orderId)
|
|
|
+ .orderBy(OrderDonView::getId).desc()
|
|
|
+ .build());
|
|
|
+
|
|
|
+ detail.setTransport(transportMapper.selectOne(Wrappers.lambdaQuery(OrderDonTransport.class).eq(OrderDonTransport::getOrderId, detail.getId()).last(" limit 1")));
|
|
|
+ detail.setWaybill(waybillMapper.selectOne(Wrappers.lambdaQuery(OrderDonWaybill.class).eq(OrderDonWaybill::getOrderId, detail.getId()).last(" limit 1")));
|
|
|
+ return detail;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public List<OrderDon> getAppleOneOrderDons(String appleOne, List<Long> skuIds, List<String> noOrderStatus, Date yesZeroDate, Date thisZeroDate) {
|
|
|
+ return orderDonMapper.getAppleOneOrderDons(appleOne, skuIds, noOrderStatus, yesZeroDate, thisZeroDate);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public AliPayParams aliPay(Long orderId, String productCode) throws Exception {
|
|
|
+ return commonAliPay(orderId, productCode, ZfbConfig.YHLX_ZfB);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ @Transactional(rollbackFor = Throwable.class)
|
|
|
+ public void aliPayNotify(Map<String, String> params) throws Exception {
|
|
|
+ //调用SDK验证签名
|
|
|
+ boolean signVerified = AlipaySignature.rsaCheckV1(params, ZfbConfig.YHLX_ZfB.getAlipayPublicKey(), BaseZfbConfig.charset, BaseZfbConfig.signType);
|
|
|
+ if (!signVerified) {
|
|
|
+ log.error("支付宝回调校验签名错误,自定义入参:{}", params.get("body"));
|
|
|
+ throw BusinessRuntimeException.getInstance("支付宝回调校验签名错误");
|
|
|
+ }
|
|
|
+ String transactionId = params.get("trade_no");
|
|
|
+ String payTimeStr = params.get("gmt_payment");
|
|
|
+ String body = Codec.DoBase64.custom().setData(params.get("body")).decodeAsText();
|
|
|
+ OrderAttach orderAttach = Jsons.parseObject(body, OrderAttach.class);
|
|
|
+ Long oderId = orderAttach.getO();
|
|
|
+ OrderDon orderDon = orderDonMapper.selectById(oderId);
|
|
|
+ if (null == orderDon) {
|
|
|
+ throw BusinessRuntimeException.getInstance("订单不存在.");
|
|
|
+ }
|
|
|
+ if (orderDon.getStatus().equals(OrderDon.Status.hasPayment)) {
|
|
|
+ log.info("支付宝已回调,重复修改状态 id:{}", orderDon.getId());
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ GoodsDonSku sku = goodsDonSkuMapper.selectById(orderDon.getSkuId());
|
|
|
+ GoodsDon goodsDon = goodsDonMapper.selectById(sku.getGoodsId());
|
|
|
+ Date payTime = DateTime.now();
|
|
|
+ if (StringUtils.isNotBlank(payTimeStr)) {
|
|
|
+ payTime = DateUtil.parse(payTimeStr, "yyyyMMddHHmmss");
|
|
|
+ }
|
|
|
+ // 更改订单状态
|
|
|
+ orderDon.setTransactionId(transactionId);
|
|
|
+ orderDon.setStatus(goodsDon.getType() == 1 && goodsDon.getSecondType() == 2 ? OrderDon.Status.complete : OrderDon.Status.hasPayment);
|
|
|
+ orderDon.setPayTime(payTime);
|
|
|
+ //修改车位状态并发送模板消息
|
|
|
+ updateCarParkAndSendMsg(goodsDon, sku, orderDon);
|
|
|
+ orderDon.setType(OrderDon.Type.ALI_PAY);
|
|
|
+ this.updateById(orderDon);
|
|
|
+ }
|
|
|
+
|
|
|
+ public void setRelation(Long relationId, Long userId) {
|
|
|
+ int noPayCount = count(Wrappers.lambdaQuery(OrderDon.class).eq(OrderDon::getUserId, userId).eq(OrderDon::getStatus, OrderDon.Status.noPayment.toString()));
|
|
|
+
|
|
|
+ if (noPayCount > 0) {
|
|
|
+ throw new BusinessRuntimeException("您有未支付订单.");
|
|
|
+ }
|
|
|
+
|
|
|
+ if (redisService.get(RedisKey.GROUPS_RELATION_NUM_KEY + relationId) != null) {
|
|
|
+ throw new BusinessRuntimeException("客官手慢啦,该座位已经有人啦!");
|
|
|
+ } else {
|
|
|
+ redisService.set(RedisKey.GROUPS_RELATION_NUM_KEY + relationId, userId, 60 * 5L);
|
|
|
+ GroupsRelation relation = groupsRelationMapper.selectById(relationId);
|
|
|
+ int count = groupsMapper.decrAvailableNum(relation.getGroupsId());
|
|
|
+ if (count == 0) {
|
|
|
+ log.error("车位异常 groupId:{}", relation.getGroupsId());
|
|
|
+ throw new BusinessRuntimeException("车位异常");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public void delRelation(Long relationId) {
|
|
|
+ redisService.del(RedisKey.GROUPS_RELATION_NUM_KEY + relationId);
|
|
|
+ GroupsRelation relation = groupsRelationMapper.selectById(relationId);
|
|
|
+ int count = groupsMapper.incrAvailableNum(relation.getGroupsId());
|
|
|
+ if (count == 0) {
|
|
|
+ log.error("车位异常 groupId:{}", relation.getGroupsId());
|
|
|
+ throw new BusinessRuntimeException("车位异常");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public void saveTransport(Long addressId, Long orderId) {
|
|
|
+ if (addressId == null) {
|
|
|
+ throw new BusinessRuntimeException("请选择收货地址.");
|
|
|
+ }
|
|
|
+ Address address = addressMapper.selectById(addressId);
|
|
|
+ if (address == null) {
|
|
|
+ throw new BusinessRuntimeException("请添加收货地址.");
|
|
|
+ }
|
|
|
+ OrderDonTransport transport = new OrderDonTransport();
|
|
|
+ transport.setOrderId(orderId);
|
|
|
+ transport.setReceiver(address.getReceiver());
|
|
|
+ transport.setPhone(address.getPhone());
|
|
|
+ transport.setProvince(address.getProvince());
|
|
|
+ transport.setCity(address.getCity());
|
|
|
+ transport.setDistrict(address.getDistrict());
|
|
|
+ transport.setAddress(address.getAddress());
|
|
|
+ orderDonTransportMapper.insert(transport);
|
|
|
+ }
|
|
|
+
|
|
|
+ public AliPayParams commonAliPay(Long orderId, String productCode, ZfbConfig zfbConfig) throws Exception {
|
|
|
+ AlipayConfig alipayConfig = new AlipayConfig();
|
|
|
+ //网关地址
|
|
|
+ alipayConfig.setServerUrl(BaseZfbConfig.url);
|
|
|
+ alipayConfig.setAppId(zfbConfig.getAppId());
|
|
|
+ alipayConfig.setPrivateKey(zfbConfig.getPrivateKey());
|
|
|
+ alipayConfig.setFormat(BaseZfbConfig.format);
|
|
|
+ alipayConfig.setCharset(BaseZfbConfig.charset);
|
|
|
+ alipayConfig.setSignType(BaseZfbConfig.signType);
|
|
|
+ alipayConfig.setAlipayPublicKey(zfbConfig.getAlipayPublicKey());
|
|
|
+ AlipayClient alipayClient = new DefaultAlipayClient(alipayConfig);
|
|
|
+ // 创建API对应的request
|
|
|
+ AlipayRequest alipayRequest = getAliAayRequest(orderId, productCode);
|
|
|
+ if (alipayRequest == null) {
|
|
|
+ throw BusinessRuntimeException.getInstance("支付宝不支持该支付方式:{0}", productCode);
|
|
|
+ }
|
|
|
+ //回调地址
|
|
|
+ String host = envCommonService.getHost();
|
|
|
+ String notifyUrl = String.format("https://%s/8081/api/%s", host, BaseZfbConfig.notifyUrl);
|
|
|
+ //去除返回地址
|
|
|
+// String returnUrl = String.format("https://%s/%s", host, BaseZfbConfig.returnUrl);
|
|
|
+ alipayRequest.setNotifyUrl(notifyUrl);
|
|
|
+// alipayRequest.setReturnUrl(returnUrl);
|
|
|
+ String form = null;
|
|
|
+ try {
|
|
|
+ //调用SDK生成表单
|
|
|
+ //pagePay 统一下单接口
|
|
|
+ form = alipayClient.pageExecute(alipayRequest).getBody();
|
|
|
+ } catch (AlipayApiException e) {
|
|
|
+ log.error("支付宝生成表单错误:{}", e == null ? null : e.getMessage());
|
|
|
+ }
|
|
|
+ log.info("支付宝返回参数:{}", form);
|
|
|
+ return new AliPayParams(form);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 支付宝获取不同的request
|
|
|
+ * @param productCode 销售产品码,与支付宝签约的产品码名称
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ private AlipayRequest getAliAayRequest(Long orderId, String productCode) throws Exception {
|
|
|
+ DateTime now = DateTime.now();
|
|
|
+ OrderAttach attach = new OrderAttach();
|
|
|
+ attach.setO(orderId);
|
|
|
+ String body = Codec.DoBase64.custom()
|
|
|
+ .setData(Jsons.toJson(attach)).encodeAsText();
|
|
|
+ OrderDon orderDon = orderDonMapper.selectById(orderId);
|
|
|
+ GoodsDon goodsDon = goodsDonMapper.selectById(orderDon.getGoodsId());
|
|
|
+ if (ZfbProductCode.MOBILE_WEB.getProductCode().equals(productCode)) {
|
|
|
+ //手机网站支付
|
|
|
+ AlipayTradeWapPayRequest alipayTradeWapPayRequest = new AlipayTradeWapPayRequest();
|
|
|
+ //手机网站支付支付参数
|
|
|
+ AlipayTradeWapPayModel alipayTradeWapPayModel = new AlipayTradeWapPayModel();
|
|
|
+ alipayTradeWapPayModel.setBody(body);
|
|
|
+ alipayTradeWapPayModel.setOutTradeNo(orderDon.getOrderNo());
|
|
|
+ alipayTradeWapPayModel.setTotalAmount(orderDon.getMoney().divide(new BigDecimal(100), 2, RoundingMode.HALF_EVEN).toString());
|
|
|
+ alipayTradeWapPayModel.setSubject(goodsDon.getTitle());
|
|
|
+ alipayTradeWapPayModel.setProductCode(productCode);
|
|
|
+ alipayTradeWapPayRequest.setBizModel(alipayTradeWapPayModel);
|
|
|
+ return alipayTradeWapPayRequest;
|
|
|
+ } else if (ZfbProductCode.PC_WEB.getProductCode().equals(productCode)) {
|
|
|
+ //电脑网站支付
|
|
|
+ AlipayTradePagePayRequest alipayTradePagePayRequest = new AlipayTradePagePayRequest();
|
|
|
+ //电脑网站支付参数
|
|
|
+ AlipayTradePagePayModel alipayTradePagePayModel = new AlipayTradePagePayModel();
|
|
|
+ alipayTradePagePayModel.setBody(body);
|
|
|
+ alipayTradePagePayModel.setOutTradeNo(orderDon.getOrderNo());
|
|
|
+ alipayTradePagePayModel.setTotalAmount(orderDon.getMoney().divide(new BigDecimal(100), 2, RoundingMode.HALF_EVEN).toString());
|
|
|
+ alipayTradePagePayModel.setSubject(goodsDon.getTitle());
|
|
|
+ alipayTradePagePayModel.setProductCode(productCode);
|
|
|
+ //5分钟订单失效时间
|
|
|
+ alipayTradePagePayModel.setTimeExpire(DateUtil.offsetMinute(now, 5).toString());
|
|
|
+ alipayTradePagePayModel.setQrPayMode("4");
|
|
|
+ alipayTradePagePayRequest.setBizModel(alipayTradePagePayModel);
|
|
|
+ return alipayTradePagePayRequest;
|
|
|
+ }
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ public void updateCarParkAndSendMsg(GoodsDon goodsDon, GoodsDonSku sku, OrderDon order) {
|
|
|
+ if (goodsDon.getType() == 1) {
|
|
|
+ //修改车位状态
|
|
|
+ GroupsRelation relation = groupsRelationMapper.selectById(order.getRelationId());
|
|
|
+ GroupsTrips groupsTrips = groupsMapper.selectById(relation.getGroupsId());
|
|
|
+ if (GroupsRelation.Status.locking.equals(relation.getStatus()) || GroupsRelation.Status.validity.equals(relation.getStatus())) {
|
|
|
+ relation.setStatus(GroupsRelation.Status.validity);
|
|
|
+ //续费后,下一次续费意愿状态为false
|
|
|
+ relation.setRenewStatus(false);
|
|
|
+ relation.setIsHandle(false);
|
|
|
+ if (GroupsTrips.Status.validity.equals(groupsTrips.getStatus())) {
|
|
|
+ //如果续费增加时间,如果首次则设置当前时间为初始时间
|
|
|
+ Date expiryTime = Optional.ofNullable(relation.getExpiryTime()).orElse(new Date());
|
|
|
+ GoodsDonSku donSku = goodsDonSkuMapper.selectById(order.getSkuId());
|
|
|
+
|
|
|
+ Date newDate = DateUtil.offset(expiryTime, DateField.MONTH, donSku.getMonths() * order.getNum());
|
|
|
+ relation.setExpiryTime(newDate);
|
|
|
+ relation.setStartTime(relation.getStartTime() == null ? new Date() : null);
|
|
|
+ } else if (GroupsTrips.Status.waiting.equals(groupsTrips.getStatus())) {
|
|
|
+ order.setStatus(OrderDon.Status.hasPayment);
|
|
|
+ }
|
|
|
+ //TODO 如未发车逻辑
|
|
|
+ groupsRelationMapper.updateById(relation);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ //新订单产生 发送模板消息给用户、客服
|
|
|
+ User user = userMapper.selectById(order.getUserId());
|
|
|
+ THREAD_POOL_TASK_EXECUTOR.execute(() -> {
|
|
|
+ try {
|
|
|
+ //发送至用户消息
|
|
|
+ newOderSendMsgByType(order, goodsDon, sku, user, user.getOpenId());
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("向用户发送新订单{}通知消息失败:{}", order.getOrderNo(), e);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ THREAD_POOL_TASK_EXECUTOR.execute(() -> {
|
|
|
+ try {
|
|
|
+ //发送至客服消息
|
|
|
+ List<CustomerService> customerServices = customerServiceMapper.selectList(null);
|
|
|
+ for (CustomerService customerService : customerServices) {
|
|
|
+ log.info("向客服{}发送新订单消息通知..", customerService.getNickName());
|
|
|
+ newOderSendMsgByType(order, goodsDon, sku, user, customerService.getOpenId());
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("向客服发送新订单{}通知消息失败:{}", order.getOrderNo(), e);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
}
|