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.*; import com.ruoyi.system.domain.dto.UserPolicyDto; import com.ruoyi.system.mapper.UserPolicyMapper; 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; @Service public class UserPolicyServiceImpl extends ServiceImpl implements UserPolicyService { @Autowired InsuranceProductService insuranceProductService; @Autowired UserAccountService userAccountService; @Autowired private PayService payService; @Autowired private PaymentRecordService paymentRecordService; @Autowired private UserKycService userKycService; @Override @Transactional(rollbackFor = Exception.class) public Result purchaseApplication(UserPolicyDto dto) throws ParseException { UserAccount userAccount = userAccountService.getOne(new LambdaQueryWrapper() .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("手机号格式不正确!"); } long count = count(new LambdaQueryWrapper() .eq(UserPolicy::getUserId, userAccount.getId()) .eq(UserPolicy::getProductId,dto.getProductId()) .eq(UserPolicy::getPolicyStatus, UserPolicy.PolicyStatus.PENDING) .and(a-> a.eq(UserPolicy::getApprovalStatus, 0) .or() .eq(UserPolicy::getApprovalStatus, 1)) ); if(count > 0){ return Result.error("请勿重复提交,如未支付请3-5分钟重新提交申请"); } InsuranceProduct insuranceProduct = insuranceProductService.getById(dto.getProductId()); if(ObjectUtil.isEmpty(insuranceProduct)){ return Result.error("该产品停止购买或已下架!"); } if(userAccount.getBalance().compareTo(insuranceProduct.getPremium()) < 0){ String orderNo = generateOrderNo(); String payOrder = payService.createOrder( insuranceProduct.getPremium(), orderNo, dto.getPayProductId() ); Map parse = (Map) 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 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); userPolicy.setIsLifelong(insuranceProduct.getTerm() == 0 ? 0 : 1); save(userPolicy); extracted(userAccount, userPolicy.getId(), orderNo,PaymentRecord.PaymentStatus.PENDING.getCode(),userPolicy.getProductId(),userPolicy.getProductName()); return Result.success(payUrl); case 401: extracted(userAccount, null, orderNo,PaymentRecord.PaymentStatus.FAILED.getCode(),null,"获取支付通道失败"); return Result.error("未授权访问支付系统"); case 403: extracted(userAccount, null, orderNo,PaymentRecord.PaymentStatus.FAILED.getCode(),null,"获取支付通道失败"); return Result.error("禁止访问支付系统"); case 404: extracted(userAccount, null, orderNo,PaymentRecord.PaymentStatus.FAILED.getCode(),null,"获取支付通道失败"); return Result.error("支付接口不存在"); case 0014: // 注意:0014可能是字符串,需要根据实际情况处理 extracted(userAccount, null, orderNo,PaymentRecord.PaymentStatus.FAILED.getCode(),null,"获取支付通道失败"); return Result.error("当前支付不可用,请更换其他支付方式!"); default: extracted(userAccount, null, orderNo,PaymentRecord.PaymentStatus.FAILED.getCode(),null,"获取支付通道失败"); // 其他错误码 String message = (String) parse.get("message"); if (message != null && !message.isEmpty()) { return Result.error("支付失败: " + message); } else { return Result.error("获取支付通道失败!"); } } }else{ userAccount.setBalance(userAccount.getBalance().subtract(insuranceProduct.getPremium())); userAccountService.updateById(userAccount); String orderNo = generateOrderNo(); 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.setIsLifelong(insuranceProduct.getTerm() == 0 ? 0 : 1); save(userPolicy); UserKyc userKyc = userKycService.getOne(new LambdaQueryWrapper() .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()); paymentRecordService.save(paymentRecord); return Result.success(); } } private void extracted(UserAccount userAccount, Integer userPolicyId, String orderNo,Integer payCode,Integer productId,String productName) { UserKyc userKyc = userKycService.getOne(new LambdaQueryWrapper() .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); paymentRecord.setProductId(productId); paymentRecord.setOrderId(userPolicyId); paymentRecord.setPayOrdeNo(orderNo); 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 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 String PREFIX = "POL"; /** * 基于时间毫秒生成唯一保单号 * 格式: POL + 时间戳 + 随机数 * 示例: POL16973512345671234 */ public String generatePolicyNumber() { long currentTimestamp = System.currentTimeMillis(); long lastTime = lastTimestamp.get(); // 如果时间戳相同,增加序列号 if (currentTimestamp == lastTime) { // 等待下一毫秒 while (currentTimestamp <= lastTime) { currentTimestamp = System.currentTimeMillis(); } } lastTimestamp.set(currentTimestamp); // 生成4位随机数 int randomNum = random.nextInt(10000); String randomStr = String.format("%04d", randomNum); return PREFIX + currentTimestamp + randomStr; } }