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.user.model.dto.EbikeUserCyclingDto;
import com.cdzy.user.model.entity.EbikeOrder;
import com.cdzy.user.model.vo.EbikeOrderVo;
import com.cdzy.user.service.EbikeOrderService;
import com.ebike.feign.clients.OperationsFeignClient;
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.query.QueryWrapper;
import jakarta.annotation.Resource;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
@ -41,13 +42,13 @@ public class EbikeOrderController {
/**
* 开始骑行生成订单开锁
*
* @param orderDto 骑行信息
* @param orderDto 骑行信息 返回订单开始时间开始点位
* @ {@code 200} 添加成功{@code 500} 添加失败
*/
@PostMapping("saveRide")
public JsonResult<?> saveRide(@RequestBody @Validated EbikeUserCyclingDto orderDto) {
Long orderId = ebikeOrderService.saveRide(orderDto);
return JsonResult.success(orderId);
EbikeOrderVo result = ebikeOrderService.saveRide(orderDto);
return JsonResult.success(result);
}
/**
@ -57,7 +58,7 @@ public class EbikeOrderController {
* @ {@code 200} 添加成功{@code 500} 添加失败
*/
@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);
return JsonResult.success(userOrders);
}

View File

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

View File

@ -113,6 +113,11 @@ public class EbikeOrder implements Serializable {
*/
private String discountDetails;
/**
* 计费规则
*/
private String billingRules;
/**
* 地理位置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.entity.EbikeOrder;
import com.cdzy.user.model.vo.EbikeOrderVo;
import com.ebike.feign.model.dto.FeignEbikeDto;
import com.ebike.feign.model.dto.FeignOrderPaymentDto;
import com.ebike.feign.model.vo.FeignEbikeBikeRadiusVo;
@ -24,7 +25,7 @@ public interface EbikeOrderService extends IService<EbikeOrder> {
* @param orderDto 用户骑行信息
* @return 骑行订单
*/
Long saveRide(EbikeUserCyclingDto orderDto);
EbikeOrderVo saveRide(EbikeUserCyclingDto orderDto);
/**
* 检查历史订单

View File

@ -49,4 +49,6 @@ public interface EbikeUserService extends IService<EbikeUser> {
* @param decryptedData 微信用户信息
*/
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.model.response.JsonResult;
import com.cdzy.user.enums.OrderStatus;
import com.cdzy.user.enums.OrderType;
import com.cdzy.user.mapper.EbikeOrderMapper;
import com.cdzy.user.model.dto.EbikeUserCyclingDto;
import com.cdzy.user.model.entity.EbikeOrder;
import com.cdzy.user.model.vo.EbikeOrderVo;
import com.cdzy.user.service.EbikeOrderService;
import com.cdzy.user.utils.RedisUtil;
import com.ebike.feign.clients.OperationsFeignClient;
@ -20,7 +22,9 @@ import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDateTime;
import java.util.List;
import static com.cdzy.user.model.entity.table.EbikeOrderTableDef.EBIKE_ORDER;
@ -48,75 +52,41 @@ public class EbikeOrderImpl extends ServiceImpl<EbikeOrderMapper, EbikeOrder> im
@Resource
private ObjectMapper objectMapper;
@Transactional
@Override
public Long saveRide(EbikeUserCyclingDto orderDto) {
// Long userId = orderDto.getUserId();
// // 校验用户当前是否存在订单
// EbikeOrder history = checkHistoryOrder(userId);
// if (history != null && history.getOrderStatus() == OrderStatus.IN_PROGRESS) {
// throw new RuntimeException("请完成当前订单后再试");
// }
// if (history != null && history.getOrderStatus() == OrderStatus.PENDING_PAYMENT) {
// throw new RuntimeException("请完成未支付订单后再试");
// }
// EbikeOrder userOrders = new EbikeOrder();
// userOrders.setUserId(userId);
// userOrders.setBikeCode(orderDto.getBikeCode());
// userOrders.setOrderType(OrderType.ONCE);
// userOrders.setStartTime(LocalDateTime.now());
// // 获取车辆基本信息
// JsonResult<FeignEbikeBikeInfoVo> jsonResult = operationsFeignClient.getEbikeInfoByCode(orderDto.getBikeCode());
// if (jsonResult.getCode() != Code.SUCCESS) {
// throw new RuntimeException("获取车辆信息失败");
// }
// FeignEbikeBikeInfoVo bikeInfoVo = jsonResult.getData();
// // 校验车辆是否可用
// validateBikeUsable(bikeInfoVo);
// // 中控基本信息
// FeignEbikeEcuInfoVo ecuInfo = bikeInfoVo.getEbikeEcuInfo();
// JsonResult<FeignEbikeRegionVo> operationResult = operationsFeignClient.getOperationById(bikeInfoVo.getRegionId());
// if (operationResult.getCode() != Code.SUCCESS) {
// throw new RuntimeException("获取运营区信息失败");
// }
// FeignEbikeRegionVo regionDto = operationResult.getData();
// FeignEbikeConfigurationVo configurationVo = regionDto.getConfigurationVo();
//
// if (configurationVo == null || Objects.equals(configurationVo.getIsOperate(), EbikeRegionInOperation.OUT)) {
// 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;
public EbikeOrderVo saveRide(EbikeUserCyclingDto orderDto) {
Long userId = orderDto.getUserId();
// 校验用户当前是否存在订单
EbikeOrder history = checkHistoryOrder(userId);
if (history != null && history.getOrderStatus() == OrderStatus.IN_PROGRESS) {
throw new RuntimeException("请完成当前订单后再试");
}
if (history != null && history.getOrderStatus() == OrderStatus.PENDING_PAYMENT) {
throw new RuntimeException("请完成未支付订单后再试");
}
EbikeOrder userOrders = new EbikeOrder();
userOrders.setUserId(userId);
userOrders.setBikeCode(orderDto.getBikeCode());
userOrders.setOrderType(OrderType.ONCE);
userOrders.setStartLocation(orderDto.getStartPoint());
userOrders.setStartTime(LocalDateTime.now());
save(userOrders);
// todo 开锁 1.开锁成功骑行 2.开锁失败订单标记为已取消
boolean unlockSuccess = false;
// 远程调用是否开锁成功
// 开锁失败 -> 订单回滚
if (!unlockSuccess) {
userOrders.setOrderStatus(OrderStatus.CANCELLED);
userOrders.setCancelTime(LocalDateTime.now());
updateById(userOrders);
throw new EbikeException("开始失败!");
}
// 状态返回
EbikeOrderVo userOrder = new EbikeOrderVo();
userOrder.setOrderId(userOrders.getOrderId());
userOrder.setOrderTime(userOrders.getCreateTime());
return userOrder;
}
@Override

View File

@ -1,6 +1,5 @@
package com.cdzy.user.service.impl;
import cn.dev33.satoken.stp.StpUtil;
import com.cdzy.user.enums.UserStatus;
import com.cdzy.user.mapper.EbikeUserMapper;
@ -114,7 +113,7 @@ public class EbikeUserServiceImpl extends ServiceImpl<EbikeUserMapper, EbikeUser
ebikeUser.setAvatar(getSafeText(profile, "avatarUrl"));
ebikeUser.setGender(getSafeInt(profile, "gender"));
ebikeUser.setCountry(getSafeText(profile, "country"));
ebikeUser.setProvince(getSafeText(profile, "city"));
ebikeUser.setProvince(getSafeText(profile, "province"));
ebikeUser.setCity(getSafeText(profile, "city"));
ebikeUser.setUpdateTime(LocalDateTime.now());
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) {
return node.has(fieldName) && !node.get(fieldName).isNull()
? 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.enums.RealNameAttestationStatus;
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.vo.EbikeUserVo;
import com.cdzy.user.service.EbikeUserRealInfoService;
import com.cdzy.user.service.EbikeUserService;
import com.fasterxml.jackson.core.JsonProcessingException;
@ -148,11 +148,16 @@ public class VerifyUtil {
* @return 验证结果
*/
public JsonResult<?> verifyRealName(UserValidateDto userValidateDto) {
EbikeUser ebikeUser = ebikeUserService.getById(userValidateDto.getUserId());
if (ebikeUser == null) {
log.error("用户不存在");
EbikeUserVo userInfo = ebikeUserService.getUserInfoByUserId(userValidateDto.getUserId());
if (userInfo == null) {
log.error("用户{}不存在", userValidateDto.getUserId());
return JsonResult.failed("用户不存在");
}
// 校验是否已进行验证
Integer realNameStatus = userInfo.getUserRealNameStatus();
if (realNameStatus != null && realNameStatus.equals(RealNameAttestationStatus.CERTIFIED)) {
return JsonResult.failed("用户已实名验证");
}
try {
// 1. 加密数据
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",
"coupon_ids" varchar(255) COLLATE "pg_catalog"."default",
"discount_details" jsonb,
"billing_rules" jsonb,
"geo_hash" varchar(12) COLLATE "pg_catalog"."default",
"start_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"."coupon_ids" IS '使用卡券ID集合JSON数组';
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"."start_location" IS '骑行初始点';
COMMENT ON COLUMN "public"."ebike_order"."end_location" IS '骑行还车点';