src/main/java/cc/mrbird/febs/mall/service/impl/ApiMallAppServiceImpl.java
@@ -1,34 +1,39 @@
package cc.mrbird.febs.mall.service.impl;
import cc.mrbird.febs.common.entity.FebsResponse;
import cc.mrbird.febs.common.enumerates.OrderStatusEnum;
import cc.mrbird.febs.common.exception.FebsException;
import cc.mrbird.febs.common.utils.AppContants;
import cc.mrbird.febs.common.utils.LoginUserUtil;
import cc.mrbird.febs.common.utils.MallUtils;
import cc.mrbird.febs.common.utils.RedisUtils;
import cc.mrbird.febs.mall.conversion.MallOrderInfoConversion;
import cc.mrbird.febs.mall.dto.*;
import cc.mrbird.febs.mall.entity.MallAppMember;
import cc.mrbird.febs.mall.entity.MallMember;
import cc.mrbird.febs.mall.mapper.MallAppMemberMapper;
import cc.mrbird.febs.mall.mapper.MallGoodsCategoryMapper;
import cc.mrbird.febs.mall.mapper.MallGoodsMapper;
import cc.mrbird.febs.mall.mapper.MallMemberMapper;
import cc.mrbird.febs.mall.entity.*;
import cc.mrbird.febs.mall.mapper.*;
import cc.mrbird.febs.mall.service.IApiMallAppService;
import cc.mrbird.febs.mall.vo.ApiMallAppMemberInfoVo;
import cc.mrbird.febs.mall.vo.ApiMallGoodsListVo;
import cc.mrbird.febs.mall.vo.MallGoodsCategoryVo;
import cc.mrbird.febs.mall.vo.MallGoodsListVo;
import cc.mrbird.febs.mall.vo.*;
import cc.mrbird.febs.pay.service.IXcxCodePayService;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.asymmetric.KeyType;
import cn.hutool.crypto.asymmetric.RSA;
import cn.hutool.db.sql.Order;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -42,7 +47,14 @@
    private final MallMemberMapper mallMemberMapper;
    private final MallGoodsCategoryMapper mallGoodsCategoryMapper;
    private final MallGoodsMapper mallGoodsMapper;
    private final MallOrderInfoMapper mallOrderInfoMapper;
    private final MallOrderItemMapper mallOrderItemMapper;
    private final MallMemberWalletMapper mallMemberWalletMapper;
    private final IXcxCodePayService xcxCodePayService;
    public static void main(String[] args) {
        System.out.println(SecureUtil.md5("a123456"));
    }
    @Override
    public FebsResponse appToLogin(LoginDto loginDto) {
        String md5Pwd = SecureUtil.md5(loginDto.getPassword());
@@ -72,7 +84,7 @@
    @Override
    public FebsResponse appMemberInfo(ApiMallAppMemberInfoDto apiMallAppMemberInfoDto) {
        Long memberId = LoginUserUtil.getLoginUser().getId();
//        Long memberId = LoginUserUtil.getLoginUser().getId();
        List<ApiMallAppMemberInfoVo> mallMembers = this.baseMapper.selectMemberInfoLikePhone(apiMallAppMemberInfoDto.getPhone());
        return new FebsResponse().success().data(mallMembers);
    }
@@ -90,10 +102,299 @@
    }
    @Override
    @Transactional
    public FebsResponse createAppOrder(ApiAddOrderDto addOrderDto) {
        if(ObjectUtil.isNotEmpty(addOrderDto.getOrderId())){
            MallOrderInfo mallOrderInfo = mallOrderInfoMapper.selectById(addOrderDto.getOrderId());
            if(ObjectUtil.isNotEmpty(mallOrderInfo)){
                mallOrderInfo.setStatus(OrderStatusEnum.CANCEL.getValue());
                mallOrderInfoMapper.updateById(mallOrderInfo);
            }
        }
        MallMemberWallet mallMemberWallet = mallMemberWalletMapper.selectWalletByMemberId(addOrderDto.getMemberId());
        if (ObjectUtil.isEmpty(mallMemberWallet)) {
            throw new FebsException("用户钱包不存在。");
        }
        if (CollUtil.isEmpty(addOrderDto.getItems())) {
            throw new FebsException("商品明细不能为空。");
        }
        Integer type = addOrderDto.getType();
        String orderNo = MallUtils.getOrderNum();
        MallOrderInfo orderInfo = new MallOrderInfo();
        orderInfo.setOrderNo(orderNo);
        orderInfo.setIsApp(AppContants.IS_APP_ORDER);
        orderInfo.setOrderTime(new Date());
        orderInfo.setMemberId(addOrderDto.getMemberId());
        orderInfo.setPayResult(2);
        //会员结算
        orderInfo.setStatus(OrderStatusEnum.WAIT_PAY.getValue());
        mallOrderInfoMapper.insert(orderInfo);
        BigDecimal total = BigDecimal.ZERO;//总支付金额
        //订单子表记录
        for (ApiAddOrderItemDto item : addOrderDto.getItems()) {
            MallOrderItem orderItem = new MallOrderItem();
            MallGoods mallGoods = mallGoodsMapper.selectById(item.getId());
            //现价
            BigDecimal presentPrice = new BigDecimal(mallGoods.getPresentPrice());
            BigDecimal amount = presentPrice.multiply(item.getCnt());
            orderItem.setAmount(amount);
            orderItem.setOrderId(orderInfo.getId());
            orderItem.setPrice(presentPrice);
            orderItem.setAppCnt(item.getCnt());
            orderItem.setGoodsId(mallGoods.getId());
            orderItem.setGoodsName(mallGoods.getGoodsName());
            orderItem.setSkuImage(mallGoods.getThumb());
            orderItem.setState(1);
//        return new FebsResponse().success().data(orderId).message("创建订单成功");
        return new FebsResponse().success().message("创建订单成功");
            total = total.add(amount);
            mallOrderItemMapper.insert(orderItem);
        }
        orderInfo.setAmount(total);
        orderInfo.setMemberId(mallMemberWallet.getMemberId());
        //折扣费用
        if(AppContants.INSURE_ORDER_MEMBER.equals(type)){
            BigDecimal score = mallMemberWallet.getScore();//积分
            BigDecimal balance = mallMemberWallet.getBalance();//余额
            //这里将运费定义成折扣总金额
            /**
             * 积分 + 余额 1:1来折扣支付金额
             */
            BigDecimal totalCarriage = BigDecimal.ZERO;//总折扣金额
            BigDecimal memberAmount = score.add(balance);//用户积分加余额总数
            if(memberAmount.compareTo(BigDecimal.ZERO) > 0){
                //折扣金额
                if(total.compareTo(memberAmount) >= 0){
                    totalCarriage = memberAmount;
                }else{
                    totalCarriage = total;
                }
            }
            orderInfo.setCarriage(totalCarriage);
        }
        mallOrderInfoMapper.updateById(orderInfo);
        Map<String, Object> orderInfoMap = new HashMap<>();
        orderInfoMap.put("orderId", orderInfo.getId());
        orderInfoMap.put("totalAmount", orderInfo.getAmount());
        orderInfoMap.put("totalCarriage", orderInfo.getCarriage());
        return new FebsResponse().success().data(orderInfoMap);
    }
    @Override
    public FebsResponse registAppOrder(ApiRegistAppOrderDto addOrderDto) {
        String orderNo = MallUtils.getOrderNum();
        MallOrderInfo orderInfo = new MallOrderInfo();
        orderInfo.setOrderNo(orderNo);
        orderInfo.setIsApp(AppContants.IS_APP_ORDER);
        orderInfo.setOrderTime(new Date());
        orderInfo.setStatus(OrderStatusEnum.WAIT_PAY.getValue());
        orderInfo.setPayResult(2);
        if (CollUtil.isEmpty(addOrderDto.getItems())) {
            throw new FebsException("商品明细不能为空。");
        }
        mallOrderInfoMapper.insert(orderInfo);
        BigDecimal total = BigDecimal.ZERO;//总支付金额
        //订单子表记录
        for (ApiAddOrderItemDto item : addOrderDto.getItems()) {
            MallOrderItem orderItem = new MallOrderItem();
            MallGoods mallGoods = mallGoodsMapper.selectById(item.getId());
            //现价
            BigDecimal presentPrice = new BigDecimal(mallGoods.getPresentPrice());
            BigDecimal amount = presentPrice.multiply(item.getCnt());
            orderItem.setAmount(amount);
            orderItem.setOrderId(orderInfo.getId());
            orderItem.setPrice(presentPrice);
            orderItem.setAppCnt(item.getCnt());
            orderItem.setGoodsId(mallGoods.getId());
            orderItem.setGoodsName(mallGoods.getGoodsName());
            orderItem.setSkuImage(mallGoods.getThumb());
            orderItem.setState(1);
            mallOrderItemMapper.insert(orderItem);
            total = total.add(amount);
        }
        orderInfo.setAmount(total);
        mallOrderInfoMapper.updateById(orderInfo);
        Integer cnt = 0;
        List<MallOrderInfo> mallOrderInfos = mallOrderInfoMapper.selectOrderInfoByStatusIsApp(OrderStatusEnum.WAIT_PAY.getValue());
        if(ObjectUtil.isNotEmpty(mallOrderInfos)){
            cnt = mallOrderInfos.size();
        }
        return new FebsResponse().success().data(cnt).message("操作成功");
    }
    @Override
    public FebsResponse normalInsure(ApiNormalInsureDto addOrderDto) {
        if(ObjectUtil.isNotEmpty(addOrderDto.getOrderId())){
            MallOrderInfo mallOrderInfo = mallOrderInfoMapper.selectById(addOrderDto.getOrderId());
            if(ObjectUtil.isNotEmpty(mallOrderInfo)){
                mallOrderInfo.setStatus(OrderStatusEnum.CANCEL.getValue());
                mallOrderInfoMapper.updateById(mallOrderInfo);
            }
        }
        String orderNo = MallUtils.getOrderNum();
        MallOrderInfo orderInfo = new MallOrderInfo();
        orderInfo.setOrderNo(orderNo);
        orderInfo.setIsApp(AppContants.IS_APP_ORDER);
        orderInfo.setOrderTime(new Date());
        orderInfo.setStatus(OrderStatusEnum.WAIT_PAY.getValue());
        orderInfo.setPayResult(2);
        if (CollUtil.isEmpty(addOrderDto.getItems())) {
            throw new FebsException("商品明细不能为空。");
        }
        mallOrderInfoMapper.insert(orderInfo);
        BigDecimal total = BigDecimal.ZERO;//总支付金额
        //订单子表记录
        for (ApiAddOrderItemDto item : addOrderDto.getItems()) {
            MallOrderItem orderItem = new MallOrderItem();
            MallGoods mallGoods = mallGoodsMapper.selectById(item.getId());
            //现价
            BigDecimal presentPrice = new BigDecimal(mallGoods.getPresentPrice());
            BigDecimal amount = presentPrice.multiply(item.getCnt());
            orderItem.setAmount(amount);
            orderItem.setOrderId(orderInfo.getId());
            orderItem.setPrice(presentPrice);
            orderItem.setAppCnt(item.getCnt());
            orderItem.setGoodsId(mallGoods.getId());
            orderItem.setGoodsName(mallGoods.getGoodsName());
            orderItem.setSkuImage(mallGoods.getThumb());
            orderItem.setState(1);
            total = total.add(amount);
            mallOrderItemMapper.insert(orderItem);
        }
        orderInfo.setCarriage(BigDecimal.ZERO);//折扣费用
        orderInfo.setAmount(total);
        mallOrderInfoMapper.updateById(orderInfo);
        Map<String, Object> orderInfoMap = new HashMap<>();
        orderInfoMap.put("orderId", orderInfo.getId());
        orderInfoMap.put("totalAmount", orderInfo.getAmount());
        orderInfoMap.put("totalCarriage", orderInfo.getCarriage());
        return new FebsResponse().success().data(orderInfoMap);
    }
    @Override
    public FebsResponse getOrderList(ApiGetOrderListDto orderListDto) {
        IPage<ApiGetOrderListVo> page = new Page<>(orderListDto.getPageNum(), orderListDto.getPageSize());
        orderListDto.setStatus(OrderStatusEnum.WAIT_PAY.getValue());
        IPage<ApiGetOrderListVo> apiGetOrderListVos = mallOrderInfoMapper.getAppOrderListInPage(page, orderListDto);
        if (CollUtil.isNotEmpty(apiGetOrderListVos.getRecords())) {
            apiGetOrderListVos.getRecords().forEach(item -> {
                item.setItems(mallOrderItemMapper.getAppOrderItemByOrderId(item.getId()));
            });
        }
        return new FebsResponse().success().data(apiGetOrderListVos);
    }
    @Override
    public FebsResponse getOrder(ApiGetOrderDto apiGetOrderDto) {
        Long orderId = apiGetOrderDto.getOrderId();
        ApiGetOrderListVo apiGetOrderListVo = mallOrderInfoMapper.getAppOrderByOrderId(orderId);
        if(ObjectUtil.isNotEmpty(apiGetOrderListVo)){
            apiGetOrderListVo.setItems(mallOrderItemMapper.getAppOrderItemByOrderId(apiGetOrderListVo.getId()));
        }
//        mallOrderInfoMapper.deleteById(orderId);
//        QueryWrapper<MallOrderItem> mallOrderItemQuery = new QueryWrapper<>();
//        mallOrderItemQuery.eq("order_id",orderId);
//        mallOrderItemMapper.delete(mallOrderItemQuery);
        return new FebsResponse().success().data(apiGetOrderListVo);
    }
    @Override
    public FebsResponse getOrderCancel(ApiGetOrderDto apiGetOrderDto) {
        MallOrderInfo mallOrderInfo = mallOrderInfoMapper.selectById(apiGetOrderDto.getOrderId());
        mallOrderInfo.setStatus(OrderStatusEnum.CANCEL.getValue());
        mallOrderInfoMapper.updateById(mallOrderInfo);
        return new FebsResponse().success().message("订单已取消");
    }
    @Override
    @Transactional
    public FebsResponse wxCodePay(ApiWxCodePayDto wxCodePayDto) {
        Long orderId = wxCodePayDto.getOrderId();
        MallOrderInfo mallOrderInfo = mallOrderInfoMapper.selectById(orderId);
        if(OrderStatusEnum.FINISH.getValue() == (mallOrderInfo.getStatus())){
            throw new FebsException("已支付");
        }
        BigDecimal amount = mallOrderInfo.getAmount();
        BigDecimal carriage = mallOrderInfo.getCarriage();
        //减少用户积分和余额
        if(ObjectUtil.isNotEmpty(mallOrderInfo.getMemberId())){
            BigDecimal avaAmount = carriage;//剩余需要折扣的金额
            if(avaAmount.compareTo(BigDecimal.ZERO) > 0){
                MallMemberWallet mallMemberWallet = mallMemberWalletMapper.selectWalletByMemberId(mallOrderInfo.getMemberId());
                BigDecimal score = mallMemberWallet.getScore();
                BigDecimal balance = mallMemberWallet.getBalance();
                BigDecimal memberAmount = score.add(balance);
                if(avaAmount.compareTo(memberAmount) >= 0){
                    //清零用户的积分和余额
                    mallMemberWallet.setBalance(BigDecimal.ZERO);
                    mallMemberWallet.setScore(BigDecimal.ZERO);
                    mallMemberWalletMapper.updateBalanceScoreWithId(mallMemberWallet);
                }else{
                    /**
                     * 先扣积分,再扣余额
                     */
                    if(avaAmount.compareTo(score) >= 0){
                        mallMemberWallet.setScore(BigDecimal.ZERO);
                        avaAmount = avaAmount.subtract(score);
                    }else{
                        mallMemberWallet.setScore(score.subtract(avaAmount));
                        avaAmount = BigDecimal.ZERO;
                    }
                    //积分不够
                    if(avaAmount.compareTo(BigDecimal.ZERO) > 0){
                        mallMemberWallet.setBalance(balance.subtract(avaAmount));
                    }else{
                        mallMemberWallet.setBalance(balance);
                    }
                    mallMemberWalletMapper.updateBalanceScoreWithId(mallMemberWallet);
                }
            }
        }
        String wxPayCode = wxCodePayDto.getWxPayCode();
        mallOrderInfo.setTakeCode(wxPayCode);
        List<ApiGetOrderOrderItemVo> appOrderItemByOrderId = mallOrderItemMapper.getAppOrderItemByOrderId(orderId);
        if(CollUtil.isEmpty(appOrderItemByOrderId)){
            mallOrderInfo.setName("商品");
        }else{
            mallOrderInfo.setName(appOrderItemByOrderId.get(0).getGoodsName());
        }
        mallOrderInfo.setStatus(OrderStatusEnum.FINISH.getValue());
        mallOrderInfoMapper.updateById(mallOrderInfo);
        // 发起付款码支付请求
        String payResult = "支付成功";
        if(amount.subtract(carriage).compareTo(BigDecimal.ZERO) > 0){
            /**
             * auth_code 扫码支付付款码 微信付款码规则:18位纯数字,前缀以10、11、12、13、14、15开头
             */
            String regex = "^(10|11|12|13|14|15)\\d{16}$";
            boolean flag = wxPayCode.matches(regex);
            if(!flag){
                throw new FebsException("请打开微信付款码!");
            }
            payResult = xcxCodePayService.pay(mallOrderInfo);
        }
        return new FebsResponse().success().message(payResult);
    }
    @Override
    public FebsResponse cancelOrder(Long id) {
        MallOrderInfo orderInfo = mallOrderInfoMapper.selectById(id);
        if (orderInfo == null || AppContants.DEL_FLAG_Y == orderInfo.getDelFlag()) {
            throw new FebsException("订单不存在");
        }
        if (OrderStatusEnum.WAIT_PAY.getValue() != orderInfo.getStatus()) {
            throw new FebsException("订单不是待付款, 无法取消");
        }
        orderInfo.setStatus(OrderStatusEnum.CANCEL.getValue());
        orderInfo.setCancelType(MallOrderInfo.CANCEL_BY_SELF);
        mallOrderInfoMapper.updateById(orderInfo);
        return new FebsResponse().success().message("取消成功");
    }
    public String generateAsaToken(String token) {