Merge remote-tracking branch 'origin/main'

This commit is contained in:
attiya 2025-11-10 16:51:55 +08:00
commit afdd119b3c
10 changed files with 104 additions and 80 deletions

View File

@ -4,6 +4,7 @@ import com.cdzy.common.model.request.PageParam;
import com.cdzy.common.model.response.JsonResult; import com.cdzy.common.model.response.JsonResult;
import com.cdzy.user.model.dto.EbikeUserCyclingDto; import com.cdzy.user.model.dto.EbikeUserCyclingDto;
import com.cdzy.user.model.entity.EbikeOrder; import com.cdzy.user.model.entity.EbikeOrder;
import com.cdzy.user.model.vo.EbikeOrderVo;
import com.cdzy.user.service.EbikeOrderService; import com.cdzy.user.service.EbikeOrderService;
import com.ebike.feign.clients.OperationsFeignClient; import com.ebike.feign.clients.OperationsFeignClient;
import com.ebike.feign.model.dto.FeignEbikeDto; import com.ebike.feign.model.dto.FeignEbikeDto;
@ -12,7 +13,7 @@ import com.ebike.feign.model.vo.FeignEbikeBikeRadiusVo;
import com.mybatisflex.core.paginate.Page; import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryWrapper; import com.mybatisflex.core.query.QueryWrapper;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
@ -41,13 +42,13 @@ public class EbikeOrderController {
/** /**
* 开始骑行生成订单开锁 * 开始骑行生成订单开锁
* *
* @param orderDto 骑行信息 * @param orderDto 骑行信息 返回订单开始时间开始点位
* @ {@code 200} 添加成功{@code 500} 添加失败 * @ {@code 200} 添加成功{@code 500} 添加失败
*/ */
@PostMapping("saveRide") @PostMapping("saveRide")
public JsonResult<?> saveRide(@RequestBody @Validated EbikeUserCyclingDto orderDto) { public JsonResult<?> saveRide(@RequestBody @Validated EbikeUserCyclingDto orderDto) {
Long orderId = ebikeOrderService.saveRide(orderDto); EbikeOrderVo result = ebikeOrderService.saveRide(orderDto);
return JsonResult.success(orderId); return JsonResult.success(result);
} }
/** /**
@ -57,7 +58,7 @@ public class EbikeOrderController {
* @ {@code 200} 添加成功{@code 500} 添加失败 * @ {@code 200} 添加成功{@code 500} 添加失败
*/ */
@GetMapping("checkHistoryOrder") @GetMapping("checkHistoryOrder")
public JsonResult<?> checkHistoryOrder(@Validated @NotBlank(message = "用户id不能为空") @RequestParam("userId") Long userId) { public JsonResult<?> checkHistoryOrder(@Validated @NotNull(message = "用户id不能为空") @RequestParam("userId") Long userId) {
EbikeOrder userOrders = ebikeOrderService.checkHistoryOrder(userId); EbikeOrder userOrders = ebikeOrderService.checkHistoryOrder(userId);
return JsonResult.success(userOrders); return JsonResult.success(userOrders);
} }

View File

@ -1,7 +1,11 @@
package com.cdzy.user.model.dto; package com.cdzy.user.model.dto;
import com.cdzy.user.handler.PGpointDeserializer; import com.cdzy.user.handler.PGpointDeserializer;
import com.cdzy.user.handler.PGpointSerializer;
import com.cdzy.user.handler.PGpointTypeHandler;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.mybatisflex.annotation.Column;
import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.NotNull;
import lombok.Data; import lombok.Data;
@ -32,6 +36,9 @@ public class EbikeUserCyclingDto {
/** /**
* 骑行起始点 * 骑行起始点
*/ */
@Column(typeHandler = PGpointTypeHandler.class)
@JsonSerialize(using = PGpointSerializer.class)
@JsonDeserialize(using = PGpointDeserializer.class) @JsonDeserialize(using = PGpointDeserializer.class)
@NotNull(message = "骑行起始点不能为空")
private PGpoint startPoint; private PGpoint startPoint;
} }

View File

@ -113,6 +113,11 @@ public class EbikeOrder implements Serializable {
*/ */
private String discountDetails; private String discountDetails;
/**
* 计费规则
*/
private String billingRules;
/** /**
* 地理位置GeoHash编码用于区域优惠分析 * 地理位置GeoHash编码用于区域优惠分析
*/ */

View File

@ -0,0 +1,24 @@
package com.cdzy.user.model.vo;
import lombok.Data;
import java.time.LocalDateTime;
/**
* @author: yanglei
* @since: 2025-11-10 15:48
*/
@Data
public class EbikeOrderVo {
/**
* 订单时间
*/
private Long orderId;
/**
* 订单编号
*/
private LocalDateTime orderTime;
}

View File

@ -2,6 +2,7 @@ package com.cdzy.user.service;
import com.cdzy.user.model.dto.EbikeUserCyclingDto; import com.cdzy.user.model.dto.EbikeUserCyclingDto;
import com.cdzy.user.model.entity.EbikeOrder; import com.cdzy.user.model.entity.EbikeOrder;
import com.cdzy.user.model.vo.EbikeOrderVo;
import com.ebike.feign.model.dto.FeignEbikeDto; import com.ebike.feign.model.dto.FeignEbikeDto;
import com.ebike.feign.model.dto.FeignOrderPaymentDto; import com.ebike.feign.model.dto.FeignOrderPaymentDto;
import com.ebike.feign.model.vo.FeignEbikeBikeRadiusVo; import com.ebike.feign.model.vo.FeignEbikeBikeRadiusVo;
@ -24,7 +25,7 @@ public interface EbikeOrderService extends IService<EbikeOrder> {
* @param orderDto 用户骑行信息 * @param orderDto 用户骑行信息
* @return 骑行订单 * @return 骑行订单
*/ */
Long saveRide(EbikeUserCyclingDto orderDto); EbikeOrderVo saveRide(EbikeUserCyclingDto orderDto);
/** /**
* 检查历史订单 * 检查历史订单

View File

@ -49,4 +49,6 @@ public interface EbikeUserService extends IService<EbikeUser> {
* @param decryptedData 微信用户信息 * @param decryptedData 微信用户信息
*/ */
void updateUserInfo(String decryptedData, String openId); void updateUserInfo(String decryptedData, String openId);
EbikeUserVo getUserInfoByUserId(Long userId);
} }

View File

@ -5,9 +5,11 @@ import com.cdzy.common.enums.Code;
import com.cdzy.common.ex.EbikeException; import com.cdzy.common.ex.EbikeException;
import com.cdzy.common.model.response.JsonResult; import com.cdzy.common.model.response.JsonResult;
import com.cdzy.user.enums.OrderStatus; import com.cdzy.user.enums.OrderStatus;
import com.cdzy.user.enums.OrderType;
import com.cdzy.user.mapper.EbikeOrderMapper; import com.cdzy.user.mapper.EbikeOrderMapper;
import com.cdzy.user.model.dto.EbikeUserCyclingDto; import com.cdzy.user.model.dto.EbikeUserCyclingDto;
import com.cdzy.user.model.entity.EbikeOrder; import com.cdzy.user.model.entity.EbikeOrder;
import com.cdzy.user.model.vo.EbikeOrderVo;
import com.cdzy.user.service.EbikeOrderService; import com.cdzy.user.service.EbikeOrderService;
import com.cdzy.user.utils.RedisUtil; import com.cdzy.user.utils.RedisUtil;
import com.ebike.feign.clients.OperationsFeignClient; import com.ebike.feign.clients.OperationsFeignClient;
@ -20,7 +22,9 @@ import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.spring.service.impl.ServiceImpl; import com.mybatisflex.spring.service.impl.ServiceImpl;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDateTime;
import java.util.List; import java.util.List;
import static com.cdzy.user.model.entity.table.EbikeOrderTableDef.EBIKE_ORDER; import static com.cdzy.user.model.entity.table.EbikeOrderTableDef.EBIKE_ORDER;
@ -48,75 +52,41 @@ public class EbikeOrderImpl extends ServiceImpl<EbikeOrderMapper, EbikeOrder> im
@Resource @Resource
private ObjectMapper objectMapper; private ObjectMapper objectMapper;
@Transactional
@Override @Override
public Long saveRide(EbikeUserCyclingDto orderDto) { public EbikeOrderVo saveRide(EbikeUserCyclingDto orderDto) {
// Long userId = orderDto.getUserId(); Long userId = orderDto.getUserId();
// // 校验用户当前是否存在订单 // 校验用户当前是否存在订单
// EbikeOrder history = checkHistoryOrder(userId); EbikeOrder history = checkHistoryOrder(userId);
// if (history != null && history.getOrderStatus() == OrderStatus.IN_PROGRESS) { if (history != null && history.getOrderStatus() == OrderStatus.IN_PROGRESS) {
// throw new RuntimeException("请完成当前订单后再试"); throw new RuntimeException("请完成当前订单后再试");
// } }
// if (history != null && history.getOrderStatus() == OrderStatus.PENDING_PAYMENT) { if (history != null && history.getOrderStatus() == OrderStatus.PENDING_PAYMENT) {
// throw new RuntimeException("请完成未支付订单后再试"); throw new RuntimeException("请完成未支付订单后再试");
// } }
// EbikeOrder userOrders = new EbikeOrder(); EbikeOrder userOrders = new EbikeOrder();
// userOrders.setUserId(userId); userOrders.setUserId(userId);
// userOrders.setBikeCode(orderDto.getBikeCode()); userOrders.setBikeCode(orderDto.getBikeCode());
// userOrders.setOrderType(OrderType.ONCE); userOrders.setOrderType(OrderType.ONCE);
// userOrders.setStartTime(LocalDateTime.now()); userOrders.setStartLocation(orderDto.getStartPoint());
// // 获取车辆基本信息 userOrders.setStartTime(LocalDateTime.now());
// JsonResult<FeignEbikeBikeInfoVo> jsonResult = operationsFeignClient.getEbikeInfoByCode(orderDto.getBikeCode()); save(userOrders);
// if (jsonResult.getCode() != Code.SUCCESS) { // todo 开锁 1.开锁成功骑行 2.开锁失败订单标记为已取消
// throw new RuntimeException("获取车辆信息失败"); boolean unlockSuccess = false;
// } // 远程调用是否开锁成功
// FeignEbikeBikeInfoVo bikeInfoVo = jsonResult.getData();
// // 校验车辆是否可用 // 开锁失败 -> 订单回滚
// validateBikeUsable(bikeInfoVo); if (!unlockSuccess) {
// // 中控基本信息 userOrders.setOrderStatus(OrderStatus.CANCELLED);
// FeignEbikeEcuInfoVo ecuInfo = bikeInfoVo.getEbikeEcuInfo(); userOrders.setCancelTime(LocalDateTime.now());
// JsonResult<FeignEbikeRegionVo> operationResult = operationsFeignClient.getOperationById(bikeInfoVo.getRegionId()); updateById(userOrders);
// if (operationResult.getCode() != Code.SUCCESS) { throw new EbikeException("开始失败!");
// throw new RuntimeException("获取运营区信息失败"); }
// } // 状态返回
// FeignEbikeRegionVo regionDto = operationResult.getData(); EbikeOrderVo userOrder = new EbikeOrderVo();
// FeignEbikeConfigurationVo configurationVo = regionDto.getConfigurationVo(); userOrder.setOrderId(userOrders.getOrderId());
// userOrder.setOrderTime(userOrders.getCreateTime());
// if (configurationVo == null || Objects.equals(configurationVo.getIsOperate(), EbikeRegionInOperation.OUT)) { return userOrder;
// throw new RuntimeException("当前运营区已停止运营");
// }
//
// // 使用 Jackson 替换 FastJSON
// Object redisData = redisUtil.get(ecuInfo.getEcuSn());
// ResGPSDto resGpsDto = objectMapper.convertValue(redisData, ResGPSDto.class);
// boolean pointInOperation = redisUtil.isPointInOperation(resGpsDto.getLongitude(), resGpsDto.getLatitude(), regionDto.getOrgId(), regionDto.getOperationRegionId());
// if (!pointInOperation) {
// throw new RuntimeException("当前车辆在运营区外");
// }
//
// //开锁,并且等待结果
// CompletableFuture<String> stringCompletableFuture = ebikeCoreHandler.executeCommand(ecuInfo, CmdCode.UNLOCK, Long.valueOf(bikeInfoDto.getBikeId()), userId);
// String response = stringCompletableFuture.join();
//
// try {
// JsonNode jsonNode = objectMapper.readTree(response);
// if (!jsonNode.has("code") || jsonNode.get("code").asInt() != 0) {
// throw new RuntimeException("开锁失败");
// }
// } catch (JsonProcessingException e) {
// throw new RuntimeException("开锁响应解析失败", e);
// }
//
// //添加借车单量
// Long siteRegionId = redisUtil.isPointInSiteWithSiteRegionId(resGpsDto.getLongitude(), resGpsDto.getLatitude(), regionDto.getOperationRegionId());
// operationsFeignClient.addBorrowing(siteRegionId);
// //改变骑行状态-骑行中
// operationsFeignClient.riding(bikeInfoDto.getBikeId());
// userOrders.setBikeId(bikeInfoDto.getBikeId());
// userOrders.setStartLocation(orderDto.getStartPoint());
// ebikeOrderTransactionMapper.insert(userOrders);
// //处理车辆
// return userOrders.getOrderId();
return null;
} }
@Override @Override

View File

@ -1,6 +1,5 @@
package com.cdzy.user.service.impl; package com.cdzy.user.service.impl;
import cn.dev33.satoken.stp.StpUtil; import cn.dev33.satoken.stp.StpUtil;
import com.cdzy.user.enums.UserStatus; import com.cdzy.user.enums.UserStatus;
import com.cdzy.user.mapper.EbikeUserMapper; import com.cdzy.user.mapper.EbikeUserMapper;
@ -114,7 +113,7 @@ public class EbikeUserServiceImpl extends ServiceImpl<EbikeUserMapper, EbikeUser
ebikeUser.setAvatar(getSafeText(profile, "avatarUrl")); ebikeUser.setAvatar(getSafeText(profile, "avatarUrl"));
ebikeUser.setGender(getSafeInt(profile, "gender")); ebikeUser.setGender(getSafeInt(profile, "gender"));
ebikeUser.setCountry(getSafeText(profile, "country")); ebikeUser.setCountry(getSafeText(profile, "country"));
ebikeUser.setProvince(getSafeText(profile, "city")); ebikeUser.setProvince(getSafeText(profile, "province"));
ebikeUser.setCity(getSafeText(profile, "city")); ebikeUser.setCity(getSafeText(profile, "city"));
ebikeUser.setUpdateTime(LocalDateTime.now()); ebikeUser.setUpdateTime(LocalDateTime.now());
this.mapper.update(ebikeUser); this.mapper.update(ebikeUser);
@ -125,6 +124,14 @@ public class EbikeUserServiceImpl extends ServiceImpl<EbikeUserMapper, EbikeUser
} }
} }
@Override
public EbikeUserVo getUserInfoByUserId(Long userId) {
QueryWrapper query = buildBaseUserQuery()
.where(EBIKE_USER.USER_ID.eq(userId));
return getOneAs(query, EbikeUserVo.class);
}
private String getSafeText(JsonNode node, String fieldName) { private String getSafeText(JsonNode node, String fieldName) {
return node.has(fieldName) && !node.get(fieldName).isNull() return node.has(fieldName) && !node.get(fieldName).isNull()
? node.get(fieldName).asText() ? node.get(fieldName).asText()

View File

@ -12,8 +12,8 @@ import com.cdzy.user.config.RealNameVerifyConfig;
import com.cdzy.user.config.WechatConfig; import com.cdzy.user.config.WechatConfig;
import com.cdzy.user.enums.RealNameAttestationStatus; import com.cdzy.user.enums.RealNameAttestationStatus;
import com.cdzy.user.model.dto.UserValidateDto; import com.cdzy.user.model.dto.UserValidateDto;
import com.cdzy.user.model.entity.EbikeUser;
import com.cdzy.user.model.entity.EbikeUserRealInfo; import com.cdzy.user.model.entity.EbikeUserRealInfo;
import com.cdzy.user.model.vo.EbikeUserVo;
import com.cdzy.user.service.EbikeUserRealInfoService; import com.cdzy.user.service.EbikeUserRealInfoService;
import com.cdzy.user.service.EbikeUserService; import com.cdzy.user.service.EbikeUserService;
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonProcessingException;
@ -148,11 +148,16 @@ public class VerifyUtil {
* @return 验证结果 * @return 验证结果
*/ */
public JsonResult<?> verifyRealName(UserValidateDto userValidateDto) { public JsonResult<?> verifyRealName(UserValidateDto userValidateDto) {
EbikeUser ebikeUser = ebikeUserService.getById(userValidateDto.getUserId()); EbikeUserVo userInfo = ebikeUserService.getUserInfoByUserId(userValidateDto.getUserId());
if (ebikeUser == null) { if (userInfo == null) {
log.error("用户不存在"); log.error("用户{}不存在", userValidateDto.getUserId());
return JsonResult.failed("用户不存在"); return JsonResult.failed("用户不存在");
} }
// 校验是否已进行验证
Integer realNameStatus = userInfo.getUserRealNameStatus();
if (realNameStatus != null && realNameStatus.equals(RealNameAttestationStatus.CERTIFIED)) {
return JsonResult.failed("用户已实名验证");
}
try { try {
// 1. 加密数据 // 1. 加密数据
Map<String, String> params = new HashMap<>(); Map<String, String> params = new HashMap<>();

View File

@ -200,6 +200,7 @@ CREATE TABLE "public"."ebike_order" (
"payment_method" varchar(20) COLLATE "pg_catalog"."default", "payment_method" varchar(20) COLLATE "pg_catalog"."default",
"coupon_ids" varchar(255) COLLATE "pg_catalog"."default", "coupon_ids" varchar(255) COLLATE "pg_catalog"."default",
"discount_details" jsonb, "discount_details" jsonb,
"billing_rules" jsonb,
"geo_hash" varchar(12) COLLATE "pg_catalog"."default", "geo_hash" varchar(12) COLLATE "pg_catalog"."default",
"start_location" point DEFAULT NULL, "start_location" point DEFAULT NULL,
"end_location" point DEFAULT NULL, "end_location" point DEFAULT NULL,
@ -227,6 +228,7 @@ COMMENT ON COLUMN "public"."ebike_order"."payment_time" IS '支付成功时间';
COMMENT ON COLUMN "public"."ebike_order"."payment_method" IS '支付方式wechat/alipay/balance'; COMMENT ON COLUMN "public"."ebike_order"."payment_method" IS '支付方式wechat/alipay/balance';
COMMENT ON COLUMN "public"."ebike_order"."coupon_ids" IS '使用卡券ID集合JSON数组'; COMMENT ON COLUMN "public"."ebike_order"."coupon_ids" IS '使用卡券ID集合JSON数组';
COMMENT ON COLUMN "public"."ebike_order"."discount_details" IS '优惠明细(结构化存储,便于对账)'; COMMENT ON COLUMN "public"."ebike_order"."discount_details" IS '优惠明细(结构化存储,便于对账)';
COMMENT ON COLUMN "public"."ebike_order"."billing_rules" IS '计费规则';
COMMENT ON COLUMN "public"."ebike_order"."geo_hash" IS '地理位置GeoHash编码用于区域优惠分析'; COMMENT ON COLUMN "public"."ebike_order"."geo_hash" IS '地理位置GeoHash编码用于区域优惠分析';
COMMENT ON COLUMN "public"."ebike_order"."start_location" IS '骑行初始点'; COMMENT ON COLUMN "public"."ebike_order"."start_location" IS '骑行初始点';
COMMENT ON COLUMN "public"."ebike_order"."end_location" IS '骑行还车点'; COMMENT ON COLUMN "public"."ebike_order"."end_location" IS '骑行还车点';