package com.ruoyi.database.controller; import com.ruoyi.common.core.controller.BaseController; import com.ruoyi.common.core.domain.AjaxResult; import com.ruoyi.common.core.domain.model.LoginUserByPhone; import com.ruoyi.common.utils.bean.BeanUtils; import com.ruoyi.database.domain.*; import com.ruoyi.database.domain.vo.ParkingBillInfoVO; import com.ruoyi.database.enums.PayType; import com.ruoyi.database.service.*; import com.ruoyi.database.util.LicensePlateValidator; import com.ruoyi.framework.web.service.TokenService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import lombok.RequiredArgsConstructor; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.bind.annotation.*; import javax.servlet.http.HttpServletRequest; import java.time.Instant; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.ThreadLocalRandom; import java.util.stream.Collectors; @Api(tags = "小程序接口") @RestController @RequiredArgsConstructor @RequestMapping("/SmallProgram") public class SmallProgramController extends BaseController { private final ParkingBillInfoService parkingBillInfoService; private final AlipayService alipayService; private final BaseCustomerInfoService baseCustomerInfoService; private final WechatMiniProgramPayService wechatMiniProgramPayService; private final ParkingBillPaymentInfoService parkingBillPaymentInfoService; private final CustomerPlateNoInfoService customerPlateNoInfoService; private final TokenService tokenService; @GetMapping("/getOrder") @ApiOperation("根据车牌号查询缴费订单") @Transactional public AjaxResult getOrder(String plateNo) { ParkingBillInfo one = parkingBillInfoService.saveOrUpdateParkingBillInfo(plateNo); // ParkingBillInfo one = parkingBillInfoService.lambdaQuery() // .eq(ParkingBillInfo::getPlateNo, plateNo) // .orderByDesc(ParkingBillInfo::getCreateTime) // .last("limit 1") // .one(); if (one == null) { return AjaxResult.error("未查询到停车记录"); }else { ParkingBillInfoVO parkingBillInfoVO = new ParkingBillInfoVO(); BeanUtils.copyProperties(one, parkingBillInfoVO); parkingBillInfoVO.setTotalCostYuan(one.getTotalCostYuan().toString() + "元"); parkingBillInfoVO.setPayMoneyYuan(one.getPayMoneyYuan().toString() + "元"); parkingBillInfoVO.setDeductMoneyYuan(one.getDeductMoneyYuan().toString() + "元"); return AjaxResult.success(parkingBillInfoVO); } } @GetMapping("/getHistoryPlateNo") @ApiOperation("历史缴费车牌列表") public AjaxResult getHistoryOrder(HttpServletRequest request){ LoginUserByPhone loginUserByPhone = tokenService.getLoginUserByPhone(request); if (loginUserByPhone == null) { return AjaxResult.error("用户未登录"); } String phone = loginUserByPhone.getPhone(); List list = parkingBillPaymentInfoService.lambdaQuery() .eq(ParkingBillPaymentInfo::getPhone, phone) .eq(ParkingBillPaymentInfo::getPayStatus, 1) .list(); Map> groupedByPlateNo = list.stream() .collect(Collectors.groupingBy( ParkingBillPaymentInfo::getPlateNo, // 按车牌分组 Collectors.toList() // 收集为List )); ArrayList> maps = new ArrayList<>(); for (String plateNo : groupedByPlateNo.keySet()) { List list1 = groupedByPlateNo.get(plateNo); ParkingBillPaymentInfo parkingBillPaymentInfo = list1.get(0); Map map = new HashMap<>(); map.put("plateNo", plateNo); map.put("plateColor",parkingBillPaymentInfo.getPlateColorCn()); maps.add(map); } return AjaxResult.success(maps); } @GetMapping("/getHistoryNoPayOrder") @ApiOperation("查询历史未缴费订单") public AjaxResult getHistoryNoPayOrder(HttpServletRequest request){ LoginUserByPhone loginUserByPhone = tokenService.getLoginUserByPhone(request); if (loginUserByPhone == null) { return AjaxResult.error("用户未登录"); } List list = customerPlateNoInfoService.lambdaQuery() .eq(CustomerPlateNoInfo::getPhone, loginUserByPhone.getPhone()) .list(); List collect = list.stream().map(CustomerPlateNoInfo::getPlateNo).collect(Collectors.toList()); if (collect.isEmpty()){ return AjaxResult.success(collect); } List list1 = parkingBillInfoService.lambdaQuery() .in(ParkingBillInfo::getPlateNo, collect) .eq(ParkingBillInfo::getIsPay, 0) .list(); List parkingBillInfoVOS = new ArrayList<>(); list1.forEach(b -> { ParkingBillInfoVO parkingBillInfoVO = new ParkingBillInfoVO(); BeanUtils.copyProperties(b, parkingBillInfoVO); parkingBillInfoVO.setTotalCostYuan(b.getTotalCostYuan().toString() + "元"); parkingBillInfoVO.setPayMoneyYuan(b.getPayMoneyYuan().toString() + "元"); parkingBillInfoVO.setDeductMoneyYuan(b.getDeductMoneyYuan().toString() + "元"); parkingBillInfoVOS.add(parkingBillInfoVO); }); return AjaxResult.success(parkingBillInfoVOS); } @GetMapping("/getBindTheVehicle") @ApiOperation("查询已绑定车辆") public AjaxResult getBindTheVehicle(HttpServletRequest request){ LoginUserByPhone loginUserByPhone = tokenService.getLoginUserByPhone(request); if (loginUserByPhone == null) { return AjaxResult.error("用户未登录"); } List list = customerPlateNoInfoService.lambdaQuery() .eq(CustomerPlateNoInfo::getPhone, loginUserByPhone.getPhone()) .list(); return AjaxResult.success(list); } @PostMapping("/bindTheVehicle") @ApiOperation("绑定车辆") public AjaxResult bindTheVehicle(@RequestBody BindTheVehicle bindTheVehicle,HttpServletRequest request){ LoginUserByPhone loginUserByPhone = tokenService.getLoginUserByPhone(request); String plateNo = bindTheVehicle.getPlateNo(); if (plateNo == null || "".equals(plateNo)) { return AjaxResult.error("绑定的车牌不能为空"); }else{ boolean valid = LicensePlateValidator.isValid(plateNo); if (!valid) { return AjaxResult.error("绑定的车牌格式不正确"); } } List list = customerPlateNoInfoService.lambdaQuery() .eq(CustomerPlateNoInfo::getPlateNo, plateNo) .list(); if (list != null && list.size() > 0) { return AjaxResult.error("车牌已被绑定"); } CustomerPlateNoInfo customerPlateNoInfo = new CustomerPlateNoInfo(); customerPlateNoInfo.setPlateNo(plateNo); customerPlateNoInfo.setPlateType(bindTheVehicle.getPlateType()); customerPlateNoInfo.setPhone(loginUserByPhone.getPhone()); return toAjax(customerPlateNoInfoService.saveOrUpdate(customerPlateNoInfo)); } @PostMapping("/payFees") @ApiOperation("缴费") @Transactional public AjaxResult payFees(@RequestBody PayFees payFees,HttpServletRequest request){ LoginUserByPhone loginUserByPhone = tokenService.getLoginUserByPhone(request); ParkingBillInfo one = parkingBillInfoService.lambdaQuery() .eq(ParkingBillInfo::getBillCode, payFees.getBillCode()) .last("limit 1") .one(); if (one == null) { return AjaxResult.error("停车记录查询失败"); } ParkingBillInfo parkingBillInfo = parkingBillInfoService.saveOrUpdateParkingBillInfo(one.getPlateNo()); if (parkingBillInfo != null) { one = parkingBillInfo; } String generate = generate(loginUserByPhone.getPhone()); BaseCustomerInfo one1 = baseCustomerInfoService.lambdaQuery() .eq(BaseCustomerInfo::getPhone, loginUserByPhone.getPhone()) .last("limit 1") .one(); if (one1 == null) { return AjaxResult.error("用户信息出错"); } String openId = null; PayType payType = PayType.getByCode(payFees.getPayType()); switch (payType) { case WECHAT: openId = one1.getOpenId(); break; case ALIPAY: openId = one1.getAlipayUserId(); break; } String clientIp = wechatMiniProgramPayService.getClientIpAddress(request); Map order = createOrder(payFees, generate, openId, one, clientIp); ParkingBillPaymentInfo parkingBillPaymentInfo = new ParkingBillPaymentInfo(); parkingBillPaymentInfo.setBillCode(one.getBillCode()); parkingBillPaymentInfo.setPlateNo(one.getPlateNo()); parkingBillPaymentInfo.setPlateColor(one.getPlateColor()); parkingBillPaymentInfo.setOpenId(openId); parkingBillPaymentInfo.setPayType(payFees.getPayType()); parkingBillPaymentInfo.setPhone(loginUserByPhone.getPhone()); parkingBillPaymentInfo.setPayStatus(0); parkingBillPaymentInfo.setOrderId(generate); boolean b = parkingBillPaymentInfoService.saveOrUpdate(parkingBillPaymentInfo); if (b) { return AjaxResult.success(order); }else { return AjaxResult.error("创建订单出错"); } } /** * 创建支付宝 微信 订单 * @param payFees * @param orderId * @param openId * @param parkingBillInfo * @param clientIp * @return */ private Map createOrder(PayFees payFees, String orderId, String openId, ParkingBillInfo parkingBillInfo, String clientIp) { PayType payType = PayType.getByCode(payFees.getPayType()); switch (payType) { case WECHAT: return wechatMiniProgramPayService.createJsapiOrder( openId,orderId,parkingBillInfo.getPayMoney(), "常客隆智慧停车缴费",clientIp); case ALIPAY: return alipayService.createOrder(orderId, parkingBillInfo.getPayMoneyYuan().toString(), "常客隆智慧停车缴费",openId); default: throw new IllegalArgumentException("不支持的登录方式: " + payType); } } public static String generate(String phone) { // 1. 参数校验 if (phone == null || phone.length() < 4) { throw new IllegalArgumentException("Invalid phone number"); } // 2. 获取手机尾号(后4位更常见) String phoneSuffix = phone.substring(phone.length() - 4); // 3. 使用更精确的时间戳 String timePart = Instant.now().toEpochMilli() + ""; // 毫秒时间戳 // 4. 增加更多随机性 int random = ThreadLocalRandom.current().nextInt(1000, 9999); return phoneSuffix + timePart.substring(timePart.length() - 10) + random; } }