1
zj
2025-11-21 2ec5c14a87bce4cb6ccba7a1bd87708bcce055a9
ruoyi-admin/src/main/java/com/ruoyi/im/service/impl/UserPolicyServiceImpl.java
@@ -1,22 +1,39 @@
package com.ruoyi.im.service.impl;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSON;
import cn.hutool.json.JSONUtil;
import com.alibaba.druid.support.json.JSONUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.im.comm.Result;
import com.ruoyi.im.service.InsuranceProductService;
import com.ruoyi.im.service.UserKycService;
import com.ruoyi.im.service.UserPolicyService;
import com.ruoyi.im.util.PayService;
import com.ruoyi.im.util.ValidatorUtil;
import com.ruoyi.system.domain.InsuranceProduct;
import com.ruoyi.system.domain.UserAccount;
import com.ruoyi.system.domain.UserPolicy;
import com.ruoyi.imenum.PaymentMode;
import com.ruoyi.system.domain.*;
import com.ruoyi.system.domain.dto.UserPolicyDto;
import com.ruoyi.system.mapper.SystemConfigurationMapper;
import com.ruoyi.system.mapper.UserPolicyMapper;
import com.ruoyi.system.service.FundsLogService;
import com.ruoyi.system.service.GroupWelcomeConfigService;
import com.ruoyi.system.service.PaymentRecordService;
import com.ruoyi.system.service.UserAccountService;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
import java.text.ParseException;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.atomic.AtomicLong;
@@ -27,55 +44,322 @@
    InsuranceProductService insuranceProductService;
    @Autowired
    UserAccountService userAccountService;
    @Autowired
    private PayService payService;
    @Autowired
    private PaymentRecordService paymentRecordService;
    @Autowired
    private UserKycService userKycService;
    @Autowired
    private GroupWelcomeConfigService groupWelcomeConfigService;
    @Autowired
    private FundsLogService fundsLogService;
    @Autowired
    private SystemConfigurationMapper systemConfigurationMapper;
    @Autowired
    private UserPolicyService userPolicyService;
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result purchaseApplication(UserPolicyDto dto) {
        UserAccount userAccount = userAccountService.getById(dto.getUserId());
    public Result purchaseApplication(UserPolicyDto dto) throws ParseException {
        UserAccount userAccount = userAccountService.getOne(new LambdaQueryWrapper<UserAccount>()
                .eq(UserAccount::getAccount,dto.getAccount()));
        if(ObjectUtil.isEmpty(userAccount)){
            return Result.error("请重新登录,未查询到你的信息!");
        }
        if(userAccount.getKycStatus() == 2){
            return Result.error("请先实名认证");
        }else if(userAccount.getKycStatus() == 0){
            return Result.error("实名认证审核中,请耐心等等");
        }
        // 验证手机号
        boolean isPhoneValid = ValidatorUtil.isValidPhone(dto.getPhone());
        if(!isPhoneValid){
            return Result.error("手机号格式不正确!");
        }
        // 验证身份证
        boolean isIdCardValid = ValidatorUtil.isValidIdCard(dto.getIdCard());
        if(!isIdCardValid){
            return Result.error("身份证格式不正确!");
        SystemConfiguration systemConfiguration = systemConfigurationMapper.selectById(1);
        if(ObjectUtil.isEmpty(systemConfiguration)){
            return Result.error("无可用支付方式!");
        }
        long count = count(new LambdaQueryWrapper<UserPolicy>()
                .eq(UserPolicy::getUserId, userAccount.getId())
                .eq(UserPolicy::getProductId,dto.getProductId())
                .eq(UserPolicy::getPolicyStatus, UserPolicy.PolicyStatus.PENDING)
                .and(a-> a.eq(UserPolicy::getApprovalStatus, 1)
                .or()
                .eq(UserPolicy::getPayStatus, 2))
        );
        if(count > 0){
            return Result.error("你已购此保险,请勿重复申请!");
        }
        InsuranceProduct insuranceProduct = insuranceProductService.getById(dto.getProductId());
        if(ObjectUtil.isEmpty(insuranceProduct)){
            return Result.error("该产品停止购买或已下架!");
        }
        UserPolicy userPolicy = new UserPolicy();
        userPolicy.setUserId(userAccount.getId());
        userPolicy.setProductId(insuranceProduct.getId());
        userPolicy.setCoverageAmount(insuranceProduct.getCoverageAmount());
        userPolicy.setPremium(insuranceProduct.getPremium());
        userPolicy.setTerm(insuranceProduct.getTerm());
        userPolicy.setName(dto.getName());
        userPolicy.setGender(dto.getGender());
        userPolicy.setBirthDate(dto.getBirthDate());
        userPolicy.setOccupation(dto.getOccupation());
        userPolicy.setIdCard(dto.getIdCard());
        userPolicy.setPhone(dto.getPhone());
        userPolicy.setPolicyNumber(generatePolicyNumber());
        userPolicy.setPolicyStatus(UserPolicy.PolicyStatus.PENDING);
        userPolicy.setCreatedAt(new Date());
        userPolicy.setUpdatedAt(new Date());
        userPolicy.setApprovalStatus(0);
        userPolicy.setIsLifelong(insuranceProduct.getTerm() == 0 ? 0 : 1);
        save(userPolicy);
        return Result.success("购买成功,注意查看资料审核状态!");
        if(!dto.getPayProductId().equals("0")){
            GroupWelcomeConfig groupWelcomeConfig = groupWelcomeConfigService.getOne(new LambdaQueryWrapper<>(GroupWelcomeConfig.class)
                    .eq(GroupWelcomeConfig::getConfigurationName, "IM-BASICS").last(" limit 1"));
            if(ObjectUtil.isNotEmpty(groupWelcomeConfig) && ObjectUtil.isNotEmpty(groupWelcomeConfig.getPaymentSwitch()) && !groupWelcomeConfig.getPaymentSwitch()){
                return Result.error("无可用支付方式!");
            }
            String orderNo = generateOrderNo();
            String payOrder = payService.createOrder(
                    insuranceProduct.getPremium(),
                    orderNo,
                    dto.getPayProductId(),
                    systemConfiguration.getCallBackUrl()
            );
            Map<String, Object> parse = (Map<String, Object>) JSONUtils.parse(payOrder);
            Integer code = (Integer) parse.get("code");
            if (code == null) {
                return Result.error("支付系统返回异常");
            }
            String payUrl;
            switch (code) {
                case 200:
                    // 成功,获取支付链接
                    payUrl = (String) parse.get("result");
                    userAccountService.updateById(userAccount);
                    UserPolicy one = getOne(new LambdaQueryWrapper<UserPolicy>()
                            .eq(UserPolicy::getUserId, userAccount.getId())
                            .eq(UserPolicy::getProductId, dto.getProductId())
                            .eq(UserPolicy::getPolicyStatus, UserPolicy.PolicyStatus.PENDING)
                            .eq(UserPolicy::getApprovalStatus, 0)
                            .ne(UserPolicy::getPayStatus, 2)
                    );
                    PaymentMode payment = PaymentMode.getByCode(dto.getPayProductId());
                    if(ObjectUtil.isEmpty(one)){
                        UserPolicy userPolicy = new UserPolicy();
                        userPolicy.setAccount(userAccount.getAccount());
                        userPolicy.setProductName(insuranceProduct.getProductName());
                        userPolicy.setUserId(userAccount.getId());
                        userPolicy.setProductId(insuranceProduct.getId());
                        userPolicy.setCoverageAmount(insuranceProduct.getCoverageAmount());
                        userPolicy.setPremium(insuranceProduct.getPremium());
                        userPolicy.setTerm(insuranceProduct.getTerm());
                        userPolicy.setName(dto.getName());
                        userPolicy.setGender(dto.getGender());
                        userPolicy.setPayStatus(1);
                        userPolicy.setOrderNo(orderNo);
                        userPolicy.setBirthDate(LocalDate.parse(dto.getBirthDate()));
                        userPolicy.setNumberDays(insuranceProduct.getNumberDays());
                        userPolicy.setOccupation(dto.getOccupation());
                        userPolicy.setIdCard(dto.getIdCard());
                        userPolicy.setPhone(dto.getPhone());
                        userPolicy.setPolicyNumber(generatePolicyNumber());
                        userPolicy.setPolicyStatus(UserPolicy.PolicyStatus.PENDING);
                        userPolicy.setCreatedAt(new Date());
                        userPolicy.setUpdatedAt(new Date());
                        userPolicy.setApprovalStatus(0);
                        if (payment != null) {
                            userPolicy.setModePayment(payment.getMode());
                        } else {
                            // 处理未知支付方式
                            userPolicy.setModePayment(0);
                        }
                        userPolicy.setIsLifelong(insuranceProduct.getTerm() == 0 ? 0 : 1);
                        save(userPolicy);
                        extracted(userAccount, userPolicy.getId(), orderNo,PaymentRecord.PaymentStatus.PENDING.getCode(),userPolicy.getProductId(),userPolicy.getProductName(),payment.getMode());
                        return Result.success(payUrl);
                    }else{
                        extracted(userAccount, one.getId(), orderNo,PaymentRecord.PaymentStatus.PENDING.getCode(),one.getProductId(),one.getProductName(),payment.getMode());
                        return Result.success(payUrl);
                    }
                case 401:
                    extracted(userAccount, null, orderNo,PaymentRecord.PaymentStatus.FAILED.getCode(),null,"获取支付通道失败",0);
                    return Result.error("未授权访问支付系统");
                case 403:
                    extracted(userAccount, null, orderNo,PaymentRecord.PaymentStatus.FAILED.getCode(),null,"获取支付通道失败",0);
                    return Result.error("禁止访问支付系统");
                case 404:
                    extracted(userAccount, null, orderNo,PaymentRecord.PaymentStatus.FAILED.getCode(),null,"获取支付通道失败",0);
                    return Result.error("支付接口不存在");
                case 0014: // 注意:0014可能是字符串,需要根据实际情况处理
                    extracted(userAccount, null, orderNo,PaymentRecord.PaymentStatus.FAILED.getCode(),null,"获取支付通道失败",0);
                    return Result.error("当前支付不可用,请更换其他支付方式!");
                default:
                    extracted(userAccount, null, orderNo,PaymentRecord.PaymentStatus.FAILED.getCode(),null,"获取支付通道失败",0);
                    // 其他错误码
                    String message = (String) parse.get("message");
                    if (message != null && !message.isEmpty()) {
                        return Result.error("支付失败: " + message);
                    } else {
                        return Result.error("获取支付通道失败!");
                    }
            }
        }else{
            if(userAccount.getBalance().compareTo(insuranceProduct.getPremium()) < 0){
                return Result.error("余额不足!");
            }
            userAccount.setBalance(userAccount.getBalance().subtract(insuranceProduct.getPremium()));
            userAccountService.updateById(userAccount);
            String orderNo = generateOrderNo();
            UserPolicy one = getOne(new LambdaQueryWrapper<UserPolicy>()
                    .eq(UserPolicy::getUserId, userAccount.getId())
                    .eq(UserPolicy::getProductId, dto.getProductId())
                    .eq(UserPolicy::getPolicyStatus, UserPolicy.PolicyStatus.PENDING)
                    .eq(UserPolicy::getApprovalStatus, 0)
                    .ne(UserPolicy::getPayStatus, 2)
            );
            if(ObjectUtil.isEmpty(one)){
                UserPolicy userPolicy = new UserPolicy();
                userPolicy.setAccount(userAccount.getAccount());
                userPolicy.setProductName(insuranceProduct.getProductName());
                userPolicy.setUserId(userAccount.getId());
                userPolicy.setProductId(insuranceProduct.getId());
                userPolicy.setCoverageAmount(insuranceProduct.getCoverageAmount());
                userPolicy.setPremium(insuranceProduct.getPremium());
                userPolicy.setTerm(insuranceProduct.getTerm());
                userPolicy.setName(dto.getName());
                userPolicy.setGender(dto.getGender());
                userPolicy.setPayStatus(2);
                userPolicy.setOrderNo(orderNo);
                userPolicy.setBirthDate(LocalDate.parse(dto.getBirthDate()));
                userPolicy.setNumberDays(insuranceProduct.getNumberDays());
                userPolicy.setOccupation(dto.getOccupation());
                userPolicy.setIdCard(dto.getIdCard());
                userPolicy.setPhone(dto.getPhone());
                userPolicy.setPolicyNumber(generatePolicyNumber());
                userPolicy.setPolicyStatus(UserPolicy.PolicyStatus.PENDING);
                userPolicy.setCreatedAt(new Date());
                userPolicy.setUpdatedAt(new Date());
                userPolicy.setApprovalStatus(0);
                userPolicy.setModePayment(3);
                userPolicy.setIsLifelong(insuranceProduct.getTerm() == 0 ? 0 : 1);
                save(userPolicy);
                UserKyc userKyc = userKycService.getOne(new LambdaQueryWrapper<UserKyc>()
                        .eq(UserKyc::getAccount, userAccount.getAccount())
                );
                PaymentRecord paymentRecord = new PaymentRecord();
                paymentRecord.setUserId(userAccount.getId());
                paymentRecord.setPaymentStatus(PaymentRecord.PaymentStatus.PAID.getCode());
                paymentRecord.setProductId(userPolicy.getProductId());
                paymentRecord.setOrderId(userPolicy.getId());
                paymentRecord.setPayOrdeNo(orderNo);
                paymentRecord.setAccount(userAccount.getAccount());
                paymentRecord.setName(userKyc.getName());
                paymentRecord.setInvitationCode(userAccount.getInvitationCode());
                paymentRecord.setProductName(insuranceProduct.getProductName());
                paymentRecord.setModePayment(3);
                paymentRecordService.save(paymentRecord);
                fundsLogService.addLog(userAccount.getId(), userAccount.getAccount(), insuranceProduct.getPremium(), OperationType.USER_ORDER);
                // 生成资金日志
                return Result.success();
            }else{
                one.setApprovalStatus(0);
                one.setModePayment(3);
                one.setPayStatus(2);
                updateById(one);
                UserKyc userKyc = userKycService.getOne(new LambdaQueryWrapper<UserKyc>()
                        .eq(UserKyc::getAccount, userAccount.getAccount())
                );
                PaymentRecord paymentRecord = new PaymentRecord();
                paymentRecord.setUserId(userAccount.getId());
                paymentRecord.setPaymentStatus(PaymentRecord.PaymentStatus.PAID.getCode());
                paymentRecord.setProductId(one.getProductId());
                paymentRecord.setOrderId(one.getId());
                paymentRecord.setPayOrdeNo(orderNo);
                paymentRecord.setAccount(userAccount.getAccount());
                paymentRecord.setName(userKyc.getName());
                paymentRecord.setInvitationCode(userAccount.getInvitationCode());
                paymentRecord.setProductName(insuranceProduct.getProductName());
                paymentRecord.setModePayment(3);
                paymentRecordService.save(paymentRecord);
                fundsLogService.addLog(userAccount.getId(), userAccount.getAccount(), insuranceProduct.getPremium(), OperationType.USER_ORDER);
                // 生成资金日志
                return Result.success();
            }
        }
    }
    private void extracted(UserAccount userAccount, Integer userPolicyId,
                           String orderNo,Integer payCode,Integer productId,String productName,Integer modePayment) {
        UserKyc userKyc = userKycService.getOne(new LambdaQueryWrapper<UserKyc>()
                .eq(UserKyc::getAccount, userAccount.getAccount())
        );
        PaymentRecord paymentRecord = new PaymentRecord();
        paymentRecord.setUserId(userAccount.getId());
        paymentRecord.setAccount(userAccount.getAccount());
        paymentRecord.setName(userKyc.getName());
        paymentRecord.setInvitationCode(userAccount.getInvitationCode());
        paymentRecord.setProductName(productName);
        paymentRecord.setPaymentStatus(payCode);
        if(userPolicyId != null){
            paymentRecord.setOrderId(userPolicyId);
        }
        if(userPolicyId != null){
            paymentRecord.setOrderId(userPolicyId);
        }
        paymentRecord.setProductId(productId);
        paymentRecord.setPayOrdeNo(orderNo);
        paymentRecord.setModePayment(modePayment);
        paymentRecordService.save(paymentRecord);
    }
    private final Random random = new Random();
    /**
     * 生成随机订单号 (格式: 时间戳 + 6位随机数)
     */
    public String generateOrderNo() {
        long timestamp = System.currentTimeMillis();
        int randomNum = random.nextInt(900000) + 100000; // 6位随机数
        return "ORDER" + timestamp + randomNum;
    }
    /**
     * 处理支付结果 - 这里您自己实现业务逻辑
     */
    private void verifySign(String orderNo, String status, String amount, Map<String, String> params) {
        // TODO: 在这里实现您的具体业务逻辑
        if ("2".equals(status)) {
            // 支付成功
            System.out.println("=== 支付成功 ===");
            System.out.println("订单号: " + orderNo);
            System.out.println("金额: " + amount);
            System.out.println("=================");
            // 示例业务逻辑:
            // 1. 更新订单状态为已支付
            // 2. 记录支付时间
            // 3. 发放商品或服务
            // 4. 发送通知等
        } else if ("3".equals(status)) {
            // 业务处理完成
            System.out.println("订单 " + orderNo + " 业务处理完成");
        } else {
            System.out.println("订单 " + orderNo + " 状态: " + status);
        }
    }
    // 使用原子长整型确保线程安全
    private static final AtomicLong lastTimestamp = new AtomicLong(0);
    private static final Random random = new Random();
    private static final String PREFIX = "POL";
    /**
@@ -83,7 +367,7 @@
     * 格式: POL + 时间戳 + 随机数
     * 示例: POL16973512345671234
     */
    public static String generatePolicyNumber() {
    public String generatePolicyNumber() {
        long currentTimestamp = System.currentTimeMillis();
        long lastTime = lastTimestamp.get();