小程序接口开发:车辆绑定 缴费与历史订单查询

This commit is contained in:
hanrenchun 2025-12-01 21:00:06 +08:00
parent 66e9d8f877
commit c4b778a452
19 changed files with 1052 additions and 105 deletions

View File

@ -6,8 +6,8 @@ import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.database.domain.ParkingLotOrderInfo;
import com.ruoyi.database.service.ParkingLotOrderInfoService;
import com.ruoyi.database.domain.ParkingBillInfo;
import com.ruoyi.database.service.ParkingBillInfoService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
@ -15,42 +15,42 @@ import org.springframework.web.bind.annotation.*;
import java.util.List;
@RequestMapping("/ParkingLotOrderInfo")
@RequestMapping("/ParkingBillInfo")
@Api(tags = "订单管理")
@RestController
@RequiredArgsConstructor
public class ParkingLotOrderInfoController extends BaseController {
public class ParkingBillInfoController extends BaseController {
private final ParkingLotOrderInfoService parkingLotOrderInfoService;
private final ParkingBillInfoService parkingBillInfoService;
@GetMapping
@ApiOperation("查询订单管理")
public TableDataInfo<ParkingLotOrderInfo> list(ParkingLotOrderInfo parkingLotOrderInfo) {
public TableDataInfo<ParkingBillInfo> list(ParkingBillInfo ParkingBillInfo) {
startPage();
QueryWrapper<ParkingLotOrderInfo> queryWrapper = new QueryWrapper<>(parkingLotOrderInfo);
List<ParkingLotOrderInfo> list = parkingLotOrderInfoService.list(queryWrapper);
long size = parkingLotOrderInfoService.count(queryWrapper);
QueryWrapper<ParkingBillInfo> queryWrapper = new QueryWrapper<>(ParkingBillInfo);
List<ParkingBillInfo> list = parkingBillInfoService.list(queryWrapper);
long size = parkingBillInfoService.count(queryWrapper);
return getDataTableEnhance(list,size);
}
@PostMapping
@ApiOperation("新增订单管理")
@Log(title = "订单管理表", businessType = BusinessType.INSERT)
public AjaxResult insert(@RequestBody ParkingLotOrderInfo parkingLotOrderInfo) {
return toAjax(parkingLotOrderInfoService.save(parkingLotOrderInfo));
public AjaxResult insert(@RequestBody ParkingBillInfo ParkingBillInfo) {
return toAjax(parkingBillInfoService.save(ParkingBillInfo));
}
@PutMapping
@ApiOperation("修改订单管理")
@Log(title = "订单管理表", businessType = BusinessType.UPDATE)
public AjaxResult update(@RequestBody ParkingLotOrderInfo parkingLotOrderInfo) {
return toAjax(parkingLotOrderInfoService.updateById(parkingLotOrderInfo));
public AjaxResult update(@RequestBody ParkingBillInfo ParkingBillInfo) {
return toAjax(parkingBillInfoService.updateById(ParkingBillInfo));
}
@DeleteMapping
@ApiOperation("删除订单管理")
@Log(title = "订单管理表", businessType = BusinessType.DELETE)
public AjaxResult delete(@RequestParam("idList") List<Long> idList) {
return toAjax(parkingLotOrderInfoService.removeByIds(idList));
return toAjax(parkingBillInfoService.removeByIds(idList));
}
}

View File

@ -0,0 +1,156 @@
package com.ruoyi.database.controller;
import cn.hutool.core.util.ReUtil;
import cn.hutool.json.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
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.core.page.TableDataInfo;
import com.ruoyi.common.utils.bean.BeanUtils;
import com.ruoyi.database.domain.*;
import com.ruoyi.database.mapper.ParkingBillInfoMapper;
import com.ruoyi.database.service.CustomerPlateNoInfoService;
import com.ruoyi.database.service.ParkingBillInfoService;
import com.ruoyi.database.service.ParkingBillPaymentInfoService;
import com.ruoyi.database.util.HaiKangApiUtils;
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.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@Api(tags = "小程序接口")
@RestController
@RequiredArgsConstructor
@RequestMapping("/SmallProgram")
public class SmallProgramController extends BaseController {
private final ParkingBillInfoService parkingBillInfoService;
private final ParkingBillPaymentInfoService parkingBillPaymentInfoService;
private final CustomerPlateNoInfoService customerPlateNoInfoService;
private final TokenService tokenService;
private final HaiKangApiUtils haiKangApiUtils;
private final ObjectMapper objectMapper = new ObjectMapper();
@GetMapping("/getOrder")
@ApiOperation("根据车牌号查询缴费订单")
public AjaxResult getOrder(String plateNo) {
String parkingPaymentInfo = haiKangApiUtils.getParkingPaymentInfo(plateNo);
if(parkingPaymentInfo==null){
return AjaxResult.error("未查询到停车信息");
}
JSONObject jsonObject = new JSONObject(parkingPaymentInfo);
String data = jsonObject.getJSONObject("data").toString();
if(data==null){
return AjaxResult.error("未查询到停车信息");
}
try {
ParkingBill vehicleRecord = objectMapper.readValue(data, ParkingBill.class);
ParkingBillInfo parkingBillInfo = new ParkingBillInfo();
BeanUtils.copyProperties(vehicleRecord,parkingBillInfo);
parkingBillInfo.setPayMoneyYuan(vehicleRecord.getPayMoneyYuan());
parkingBillInfo.setDeductMoneyYuan(vehicleRecord.getDeductMoneyYuan());
parkingBillInfo.setTotalCostYuan(vehicleRecord.getTotalCostYuan());
LambdaUpdateWrapper<ParkingBillInfo> updateWrapper = new LambdaUpdateWrapper<>();
updateWrapper.eq(ParkingBillInfo::getBillCode,parkingBillInfo.getBillCode());
parkingBillInfoService.saveOrUpdate(parkingBillInfo,updateWrapper);
return AjaxResult.success(parkingBillInfo);
} catch (JsonProcessingException e) {
return AjaxResult.error("未查询到停车信息");
}
}
@GetMapping("/getHistoryPlateNo")
@ApiOperation("历史缴费车牌列表")
public AjaxResult getHistoryOrder(HttpServletRequest request){
LoginUserByPhone loginUserByPhone = tokenService.getLoginUserByPhone(request);
String phone = loginUserByPhone.getPhone();
List<ParkingBillPaymentInfo> list = parkingBillPaymentInfoService.lambdaQuery()
.eq(ParkingBillPaymentInfo::getPhone, phone)
.eq(ParkingBillPaymentInfo::getPayStatus, 1)
.list();
Map<String, List<ParkingBillPaymentInfo>> groupedByPlateNo = list.stream()
.collect(Collectors.groupingBy(
ParkingBillPaymentInfo::getPlateNo, // 按车牌分组
Collectors.toList() // 收集为List
));
ArrayList<Map<String, String>> maps = new ArrayList<>();
for (String plateNo : groupedByPlateNo.keySet()) {
List<ParkingBillPaymentInfo> list1 = groupedByPlateNo.get(plateNo);
ParkingBillPaymentInfo parkingBillPaymentInfo = list1.get(0);
Map<String, String> 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);
return AjaxResult.success();
}
@GetMapping("/getBindTheVehicle")
@ApiOperation("查询已绑定车辆")
public AjaxResult getBindTheVehicle(HttpServletRequest request){
LoginUserByPhone loginUserByPhone = tokenService.getLoginUserByPhone(request);
List<CustomerPlateNoInfo> 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<CustomerPlateNoInfo> 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());
customerPlateNoInfoService.saveOrUpdate(customerPlateNoInfo);
return AjaxResult.success(customerPlateNoInfo);
}
}

View File

@ -0,0 +1,20 @@
package com.ruoyi.database.domain;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotBlank;
@Data
public class BindTheVehicle {
@NotBlank(message = "不能为空")
private String plateNo;
@ApiModelProperty("车牌类型 1蓝牌车 2黄牌车 3新能源车")
@NotBlank(message = "车牌类型不能为空")
private Integer plateType;
}

View File

@ -0,0 +1,20 @@
package com.ruoyi.database.domain;
import lombok.Data;
/**
* 进出场图片信息
*/
@Data
public class ImageInfo {
/**
* 图片类型
*/
private Integer type;
/**
* 图片URL
*/
private String url;
}

View File

@ -0,0 +1,100 @@
package com.ruoyi.database.domain;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import java.math.BigDecimal;
import java.util.Date;
/**
* 停车场账单信息
*/
@Data
public class ParkingBill {
/**
* 账单编号
*/
@JsonProperty("billCode")
private String billCode;
/**
* 停车场编码
*/
@JsonProperty("parkCode")
private String parkCode;
/**
* 停车场名称
*/
@JsonProperty("parkName")
private String parkName;
/**
* 车牌号
*/
@JsonProperty("plateNo")
private String plateNo;
/**
* 车牌颜色 (1:蓝色, 2:黄色, 3:黑色, 4:白色, 5:绿色, 6:其他)
*/
@JsonProperty("plateColor")
private Integer plateColor;
/**
* 入场时间 (时间戳)
*/
@JsonProperty("enterTime")
private Long enterTime;
/**
* 离场时间 (时间戳)
*/
@JsonProperty("costTime")
private Long costTime;
/**
* 停车时长 (分钟)
*/
@JsonProperty("parkPeriodTime")
private Integer parkPeriodTime;
/**
* 总费用 (单位)
*/
@JsonProperty("totalCost")
private Integer totalCost;
/**
* 抵扣金额 (单位)
*/
@JsonProperty("deductMoney")
private Integer deductMoney;
/**
* 实付金额 (单位)
*/
@JsonProperty("payMoney")
private Integer payMoney;
/**
* 入场记录唯一标识
*/
@JsonProperty("inUnid")
private String inUnid;
public BigDecimal getTotalCostYuan() {
return totalCost != null ? BigDecimal.valueOf(totalCost).divide(BigDecimal.valueOf(100)) : null;
}
public BigDecimal getDeductMoneyYuan() {
return deductMoney != null ? BigDecimal.valueOf(deductMoney).divide(BigDecimal.valueOf(100)) : null;
}
public BigDecimal getPayMoneyYuan() {
return payMoney != null ? BigDecimal.valueOf(payMoney).divide(BigDecimal.valueOf(100)) : null;
}
}

View File

@ -0,0 +1,165 @@
package com.ruoyi.database.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.core.domain.BaseEntity;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.math.BigDecimal;
import java.util.Date;
/**
* 停车场账单表(ParkingBillInfo)实体类
*
* @author makejava
* @since 2025-12-01 15:37:06
*/
@Data
@EqualsAndHashCode(callSuper = false)
@TableName(value = "parking_bill_info")
@ApiModel(value = "ParkingBillInfo", description = "停车场账单表")
public class ParkingBillInfo {
/**
* 主键ID
*/
@ApiModelProperty("主键")
@TableId(value = "id", type = IdType.AUTO)
private Long id;
/**
* 账单编号
*/
@ApiModelProperty("账单编号")
@Excel(name = "账单编号")
private String billCode;
/**
* 停车场编码
*/
@ApiModelProperty("停车场编码")
@Excel(name = "停车场编码")
private String parkCode;
/**
* 停车场名称
*/
@ApiModelProperty("停车场名称")
@Excel(name = "停车场名称")
private String parkName;
/**
* 车牌号
*/
@ApiModelProperty("车牌号")
@Excel(name = "车牌号")
private String plateNo;
/**
* 车牌颜色
*/
@ApiModelProperty("车牌颜色")
@Excel(name = "车牌颜色")
private Integer plateColor;
@TableField(exist = false)
private String plateColorCn;
/**
* 入场时间戳(毫秒)
*/
@ApiModelProperty("入场时间戳(毫秒)")
@Excel(name = "入场时间戳(毫秒)")
private Long enterTime;
/**
* 离场时间戳(毫秒)
*/
@ApiModelProperty("离场时间戳(毫秒)")
@Excel(name = "离场时间戳(毫秒)")
private Long costTime;
/**
* 停车时长(分钟)
*/
@ApiModelProperty("停车时长(分钟)")
@Excel(name = "停车时长(分钟)")
private Integer parkPeriodTime;
/**
* 总费用()
*/
@ApiModelProperty("总费用(分)")
@Excel(name = "总费用(分)")
private Integer totalCost;
/**
* 总费用()
*/
@ApiModelProperty("总费用(元)")
@Excel(name = "总费用(元)")
private BigDecimal totalCostYuan;
/**
* 抵扣金额()
*/
@ApiModelProperty("抵扣金额(分)")
@Excel(name = "抵扣金额(分)")
private Integer deductMoney;
/**
* 抵扣金额()
*/
@ApiModelProperty("抵扣金额(元)")
@Excel(name = "抵扣金额(元)")
private BigDecimal deductMoneyYuan;
/**
* 实付金额()
*/
@ApiModelProperty("实付金额(分)")
@Excel(name = "实付金额(分)")
private Integer payMoney;
/**
* 实付金额()
*/
@ApiModelProperty("实付金额(元)")
@Excel(name = "实付金额(元)")
private BigDecimal payMoneyYuan;
/**
* 入场记录唯一标识
*/
@ApiModelProperty("入场记录唯一标识")
@Excel(name = "入场记录唯一标识")
private String inUnid;
/**
* 创建时间
*/
@ApiModelProperty("创建时间")
@Excel(name = "创建时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTime;
/**
* 更新时间
*/
@ApiModelProperty("更新时间")
@Excel(name = "更新时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date updateTime;
}

View File

@ -7,6 +7,7 @@ import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.core.domain.BaseEntity;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@ -15,24 +16,47 @@ import lombok.EqualsAndHashCode;
import java.util.Date;
/**
* 停车场订单表(ParkingLotOrderInfo)实体类
* 停车订单支付状态表(ParkingBillPaymentInfo)实体类
*
* @author makejava
* @since 2025-11-20 09:27:12
* @since 2025-12-01 19:08:25
*/
@Data
@EqualsAndHashCode(callSuper = false)
@TableName(value = "parking_lot_order_info")
@ApiModel(value = "ParkingLotOrderInfo", description = "停车订单表")
public class ParkingLotOrderInfo {
@TableName(value = "parking_bill_payment_info")
@ApiModel(value = "ParkingBillPaymentInfo", description = "停车订单支付状态")
public class ParkingBillPaymentInfo {
/**
* 主键
* 主键ID
*/
@ApiModelProperty("主键")
@TableId(value = "id", type = IdType.AUTO)
private Long id;
/**
* 账单编号
*/
@ApiModelProperty("账单编号")
@Excel(name = "账单编号")
private String billCode;
/**
* 车牌号
*/
@ApiModelProperty("车牌号")
@Excel(name = "车牌号")
private String plateNo;
/**
* 车牌颜色
*/
@ApiModelProperty("车牌颜色")
@Excel(name = "车牌颜色")
private Integer plateColor;
@TableField(exist = false)
private String plateColorCn;
/**
* 创建时间
*/
@ -41,13 +65,6 @@ public class ParkingLotOrderInfo {
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTime;
/**
* 创建者
*/
@ApiModelProperty("创建者")
@Excel(name = "创建者")
private Integer createBy;
/**
* 更新时间
*/
@ -57,18 +74,18 @@ public class ParkingLotOrderInfo {
private Date updateTime;
/**
* 更新者
* 微信openid
*/
@ApiModelProperty("更新者")
@Excel(name = "更新者")
private Integer updateBy;
@ApiModelProperty("微信openid")
@Excel(name = "微信openid")
private String openId;
/**
* 车牌号
* 支付宝用户ID
*/
@ApiModelProperty("车牌号")
@Excel(name = "车牌号")
private String plateNo;
@ApiModelProperty("支付宝用户ID")
@Excel(name = "支付宝用户ID")
private String alipayUserId;
/**
* 手机号
@ -78,43 +95,18 @@ public class ParkingLotOrderInfo {
private String phone;
/**
* 停车场名称
* 支付状态
*/
@ApiModelProperty("停车场名称")
@Excel(name = "停车场名称")
private String name;
@ApiModelProperty("支付状态")
@Excel(name = "支付状态")
private Integer payStatus;
/**
* 停车场编码
* 支付订单号id
*/
@ApiModelProperty("停车场编码")
@Excel(name = "停车场编码")
private String code;
/**
* 入车时间
*/
@ApiModelProperty("入车时间")
@Excel(name = "入车时间")
private Long entryTime;
@TableField(exist = false)
private String entryTimeCn;
/**
* 出车时间
*/
@ApiModelProperty("出车时间")
@Excel(name = "出车时间")
private Long departTime;
@TableField(exist = false)
private String departTimeCn;
/**
* 停车时长
*/
@ApiModelProperty("停车时长")
@Excel(name = "停车时长")
private String parkTime;
@ApiModelProperty("支付订单号id")
@Excel(name = "支付订单号id")
private String transactionId;
}

View File

@ -0,0 +1,107 @@
package com.ruoyi.database.domain;
import lombok.Data;
import lombok.ToString;
/**
* 停车场信息消息
*/
@Data
@ToString
public class ParkingLotInfo {
/**
* 停车场编码
*/
private String parkCode;
/**
* 停车场名称
*/
private String parkName;
/**
* 总车位数量
*/
private Integer totalParkingSpaceNum;
/**
* 剩余车位数量
*/
private Integer leftParkingSpaceNum;
/**
* 总固定车位数量
*/
private Integer totalFixedSpaceNum;
/**
* 剩余固定车位数量
*/
private Integer leftFixedSpaceNum;
/**
* 停车场描述
*/
private String description;
/**
* 停车场经度
*/
private String parkLongitude;
/**
* 停车场纬度
*/
private String parkLatitude;
/**
* 停车场类型 (1-路边停车场2-封闭式场库)
*/
private Integer parkType;
/**
* 停车场等级
*/
private Integer parkLevel;
/**
* 停车开始时间 (格式HH:mm)
*/
private String parkingStartTime;
/**
* 停车结束时间 (格式HH:mm)
*/
private String parkingEndTime;
/**
* 免费时长 (分钟)
*/
private String freeTime;
/**
* 总充电桩数量
*/
private Integer chargeTotalNum;
/**
* 剩余可用充电桩数量
*/
private Integer chargeLeftNum;
/**
* 停车场地址
*/
private String parkingAddress;
/**
* 收费规则描述
*/
private String payRuleDesc;
/**
* 区域名称
*/
private String areaName;
}

View File

@ -1,6 +1,6 @@
package com.ruoyi.database.domain;
import com.alipay.api.domain.ImageInfo;
import lombok.Data;
import java.util.List;

View File

@ -1,16 +1,16 @@
package com.ruoyi.database.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.ruoyi.database.domain.ParkingLotOrderInfo;
import com.ruoyi.database.domain.ParkingBillInfo;
import org.apache.ibatis.annotations.Mapper;
/**
* 停车场订单表(ParkingLotOrderInfo) Mapper 接口
* 停车场账单表(ParkingBillInfo) Mapper 接口
*
* @author makejava
* @since ${date}
*/
@Mapper
public interface ParkingLotOrderInfoMapper extends BaseMapper<ParkingLotOrderInfo> {
public interface ParkingBillInfoMapper extends BaseMapper<ParkingBillInfo> {
}

View File

@ -0,0 +1,16 @@
package com.ruoyi.database.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.ruoyi.database.domain.ParkingBillPaymentInfo;
import org.apache.ibatis.annotations.Mapper;
/**
* 停车订单支付状态表(ParkingBillPaymentInfo) Mapper 接口
*
* @author makejava
* @since ${date}
*/
@Mapper
public interface ParkingBillPaymentInfoMapper extends BaseMapper<ParkingBillPaymentInfo> {
}

View File

@ -0,0 +1,14 @@
package com.ruoyi.database.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.ruoyi.database.domain.ParkingBillInfo;
/**
* (停车场账单表)Service
*
* @author makejava
* @since 2025-12-01 15:37:06
*/
public interface ParkingBillInfoService extends IService<ParkingBillInfo> {
}

View File

@ -0,0 +1,14 @@
package com.ruoyi.database.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.ruoyi.database.domain.ParkingBillPaymentInfo;
/**
* (停车订单支付状态表)Service
*
* @author makejava
* @since 2025-12-01 19:08:25
*/
public interface ParkingBillPaymentInfoService extends IService<ParkingBillPaymentInfo> {
}

View File

@ -1,14 +0,0 @@
package com.ruoyi.database.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.ruoyi.database.domain.ParkingLotOrderInfo;
/**
* (停车场订单表)Service
*
* @author makejava
* @since 2025-11-20 09:27:12
*/
public interface ParkingLotOrderInfoService extends IService<ParkingLotOrderInfo> {
}

View File

@ -0,0 +1,19 @@
package com.ruoyi.database.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.database.domain.ParkingBillInfo;
import com.ruoyi.database.mapper.ParkingBillInfoMapper;
import com.ruoyi.database.service.ParkingBillInfoService;
import org.springframework.stereotype.Service;
/**
* (停车场账单表)ServiceImpl
*
* @author makejava
* @since 2025-12-01 15:37:06
*/
@Service
public class ParkingBillInfoServiceImpl extends ServiceImpl<ParkingBillInfoMapper, ParkingBillInfo> implements ParkingBillInfoService {
}

View File

@ -0,0 +1,19 @@
package com.ruoyi.database.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.database.domain.ParkingBillPaymentInfo;
import com.ruoyi.database.mapper.ParkingBillPaymentInfoMapper;
import com.ruoyi.database.service.ParkingBillPaymentInfoService;
import org.springframework.stereotype.Service;
/**
* (停车订单支付状态表)ServiceImpl
*
* @author makejava
* @since 2025-12-01 19:08:25
*/
@Service
public class ParkingBillPaymentInfoServiceImpl extends ServiceImpl<ParkingBillPaymentInfoMapper, ParkingBillPaymentInfo> implements ParkingBillPaymentInfoService {
}

View File

@ -1,19 +0,0 @@
package com.ruoyi.database.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.database.domain.ParkingLotOrderInfo;
import com.ruoyi.database.mapper.ParkingLotOrderInfoMapper;
import com.ruoyi.database.service.ParkingLotOrderInfoService;
import org.springframework.stereotype.Service;
/**
* (停车场订单表)ServiceImpl
*
* @author makejava
* @since 2025-11-20 09:27:12
*/
@Service
public class ParkingLotOrderInfoServiceImpl extends ServiceImpl<ParkingLotOrderInfoMapper, ParkingLotOrderInfo> implements ParkingLotOrderInfoService {
}

View File

@ -0,0 +1,160 @@
package com.ruoyi.database.util;
import cn.hutool.json.JSONObject;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.ruoyi.common.core.redis.RedisCache;
import lombok.RequiredArgsConstructor;
import org.apache.http.HttpEntity;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.concurrent.TimeUnit;
@Component
@RequiredArgsConstructor
public class HaiKangApiUtils {
private static final String HIK_URL = "https://artemis.hikparking.com";
private static final String client_id = "25799436";
private static final String client_secret = "eTe6Xy6iXFUiL9v2Qa2gTjZkqVHFK5bN";
private static final String park_code = "101CX2ALLFGY329";
private final RedisCache redisCache;
private static final int CONNECT_TIMEOUT = 5000; // 连接超时 5秒
private static final int SOCKET_TIMEOUT = 10000;
private static final String HIK_TOKEN_KEY = "HIK_TOKEN_KEY";
private static Gson gson = new GsonBuilder().create();
private static CloseableHttpClient createHttpClient() {
RequestConfig config = RequestConfig.custom()
.setConnectTimeout(CONNECT_TIMEOUT)
.setSocketTimeout(SOCKET_TIMEOUT)
.build();
return HttpClients.custom()
.setDefaultRequestConfig(config)
.build();
}
/**
* 获取海康云平台accessToken
* @return accessToken
*/
public String getAccessToken(){
String accessToken = redisCache.getCacheObject(HIK_TOKEN_KEY);
if (accessToken != null) {
return accessToken;
}
String hikAccessToken = getHikAccessToken();
if (hikAccessToken == null) {
return null;
}
JSONObject jsonObject = new JSONObject(hikAccessToken);
accessToken = jsonObject.getStr("access_token");
if (accessToken == null) {
return null;
}
redisCache.setCacheObject(HIK_TOKEN_KEY, accessToken,43199, TimeUnit.SECONDS);
return accessToken;
}
/**
* 调用海康云平台
* 获取accessToken接口
*/
public String getHikAccessToken(){
try (CloseableHttpClient client = createHttpClient()) {
HttpPost httpPost = new HttpPost(HIK_URL + "/artemis/oauth/token");
HashMap<String, String> map = new HashMap<>();
map.put("client_id", client_id);
map.put("client_secret", client_secret);
String json = gson.toJson(map);
StringEntity entity = new StringEntity(json, "UTF-8");
httpPost.setEntity(entity);
httpPost.setHeader("Content-type", "application/x-www-form-urlencoded");
CloseableHttpResponse response = client.execute(httpPost);
HttpEntity entityResponse = response.getEntity();
if (entityResponse != null) {
String res = EntityUtils.toString(entityResponse, "UTF-8");
System.out.println(res);
return res;
} else {
// 处理空响应的情况
System.err.println("Received empty response from server");
return null;
}
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 根据停车场编码
* 获取停车场详情
*/
public String getHikParkInfo(){
try (CloseableHttpClient client = createHttpClient()) {
HttpPost httpPost = new HttpPost(HIK_URL + "/artemis/api/v1/dealer/parkinfo/" + park_code);
httpPost.setHeader("access_token", getAccessToken());
CloseableHttpResponse response = client.execute(httpPost);
HttpEntity entityResponse = response.getEntity();
if (entityResponse != null) {
String res = EntityUtils.toString(entityResponse, "UTF-8");
System.out.println(res);
return res;
} else {
// 处理空响应的情况
System.err.println("Received empty response from server");
return null;
}
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 根据车牌获取车辆停车账单
*/
public String getParkingPaymentInfo(String plateNo){
try (CloseableHttpClient client = createHttpClient()) {
HttpPost httpPost = new HttpPost(HIK_URL + "/artemis/api/v1/charge/getParkingPaymentInfo");
HashMap<String, String> map = new HashMap<>();
map.put("plateNo", plateNo);
String json = gson.toJson(map);
StringEntity entity = new StringEntity(json, "UTF-8");
httpPost.setEntity(entity);
httpPost.setHeader("Content-type", "application/json");
httpPost.setHeader("access_token", getAccessToken());
CloseableHttpResponse response = client.execute(httpPost);
HttpEntity entityResponse = response.getEntity();
if (entityResponse != null) {
String res = EntityUtils.toString(entityResponse, "UTF-8");
System.out.println(res);
return res;
} else {
// 处理空响应的情况
System.err.println("Received empty response from server");
return null;
}
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}

View File

@ -0,0 +1,178 @@
package com.ruoyi.database.util;
/**
* 车牌验证工具类完整版
* 来源多个开源项目整合优化
*/
public class LicensePlateValidator {
/**
* 中国车牌正则表达式集合
*/
public static class Patterns {
// 普通民用车牌
public static final String COMMON_PLATE = "^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领][A-Z][A-Z0-9]{4,5}[A-Z0-9挂学警港澳]$";
// 新能源车牌
public static final String NEW_ENERGY_PLATE = "^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领][A-Z](([0-9]{5}[DF])|([DF][A-HJ-NP-Z0-9][0-9]{4}))$";
// 警车车牌
public static final String POLICE_PLATE = "^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领][A-Z][0-9]{4}警$";
// 武警车牌
public static final String ARMED_POLICE_PLATE = "^WJ[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领][0-9]{4}[TD]$";
// 使馆车牌
public static final String EMBASSY_PLATE = "^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领][A-Z][0-9]{4}使$";
// 教练车牌
public static final String COACH_PLATE = "^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领][A-Z][0-9]{4}学$";
}
/**
* 车牌类型枚举
*/
public enum PlateType {
COMMON(1, "普通蓝牌"),
YELLOW(2, "黄牌"),
NEW_ENERGY(3, "新能源"),
POLICE(4, "警车"),
ARMED_POLICE(5, "武警"),
EMBASSY(6, "使馆"),
COACH(7, "教练"),
UNKNOWN(0, "未知");
private final int code;
private final String desc;
PlateType(int code, String desc) {
this.code = code;
this.desc = desc;
}
public int getCode() { return code; }
public String getDesc() { return desc; }
}
/**
* 验证车牌号是否有效
* @param plateNo 车牌号
* @return 是否有效
*/
public static boolean isValid(String plateNo) {
if (plateNo == null || plateNo.trim().isEmpty()) {
return false;
}
String formatted = formatPlateNo(plateNo);
// 检查所有可能的车牌类型
return isCommonPlate(formatted) ||
isNewEnergyPlate(formatted) ||
isPolicePlate(formatted) ||
isArmedPolicePlate(formatted) ||
isEmbassyPlate(formatted) ||
isCoachPlate(formatted);
}
/**
* 检测车牌类型
* @param plateNo 车牌号
* @return 车牌类型
*/
public static PlateType detectType(String plateNo) {
if (plateNo == null || plateNo.trim().isEmpty()) {
return PlateType.UNKNOWN;
}
String formatted = formatPlateNo(plateNo);
if (isNewEnergyPlate(formatted)) {
return PlateType.NEW_ENERGY;
} else if (isCommonPlate(formatted)) {
// 区分蓝牌和黄牌通过长度和内容判断
if (formatted.length() >= 7 && formatted.matches(".*[0-9]{6}.*")) {
return PlateType.YELLOW;
}
return PlateType.COMMON;
} else if (isPolicePlate(formatted)) {
return PlateType.POLICE;
} else if (isArmedPolicePlate(formatted)) {
return PlateType.ARMED_POLICE;
} else if (isEmbassyPlate(formatted)) {
return PlateType.EMBASSY;
} else if (isCoachPlate(formatted)) {
return PlateType.COACH;
}
return PlateType.UNKNOWN;
}
/**
* 格式化车牌号统一格式
*/
public static String formatPlateNo(String plateNo) {
if (plateNo == null) return null;
// 去除所有空白字符转为大写
return plateNo.replaceAll("\\s+", "").toUpperCase();
}
// 各个类型的验证方法
private static boolean isCommonPlate(String plateNo) {
return plateNo.matches(Patterns.COMMON_PLATE);
}
private static boolean isNewEnergyPlate(String plateNo) {
return plateNo.matches(Patterns.NEW_ENERGY_PLATE);
}
private static boolean isPolicePlate(String plateNo) {
return plateNo.matches(Patterns.POLICE_PLATE);
}
private static boolean isArmedPolicePlate(String plateNo) {
return plateNo.matches(Patterns.ARMED_POLICE_PLATE);
}
private static boolean isEmbassyPlate(String plateNo) {
return plateNo.matches(Patterns.EMBASSY_PLATE);
}
private static boolean isCoachPlate(String plateNo) {
return plateNo.matches(Patterns.COACH_PLATE);
}
/**
* 获取省份简称
*/
public static String getProvince(String plateNo) {
if (plateNo == null || plateNo.length() < 1) {
return null;
}
return formatPlateNo(plateNo).substring(0, 1);
}
/**
* 测试用例
*/
public static void main(String[] args) {
String[] testPlates = {
"京A12345",
"沪AD12345",
"粤B88888",
"京A1234警",
"WJ京1234T",
"使A1234使",
"invalid"
};
for (String plate : testPlates) {
System.out.println("车牌: " + plate);
System.out.println("是否有效: " + isValid(plate));
System.out.println("类型: " + detectType(plate));
System.out.println("省份: " + getProvince(plate));
System.out.println("格式化: " + formatPlateNo(plate));
System.out.println("---");
}
}
}