diff --git a/ebike-common/pom.xml b/ebike-common/pom.xml
index ca49f67c..05170cc3 100644
--- a/ebike-common/pom.xml
+++ b/ebike-common/pom.xml
@@ -37,6 +37,20 @@
influxdb-client-java
6.10.0
+
+
+
+ org.locationtech.jts
+ jts-core
+ 1.19.0
+
+
+
+ org.osgeo
+ proj4j
+ 0.1.0
+
+
diff --git a/ebike-common/src/main/java/com/cdzy/common/utils/CoordinateUtil.java b/ebike-common/src/main/java/com/cdzy/common/utils/CoordinateUtil.java
index b9037810..ef6b5f80 100644
--- a/ebike-common/src/main/java/com/cdzy/common/utils/CoordinateUtil.java
+++ b/ebike-common/src/main/java/com/cdzy/common/utils/CoordinateUtil.java
@@ -1,5 +1,12 @@
package com.cdzy.common.utils;
+import org.locationtech.jts.geom.Coordinate;
+import org.locationtech.jts.geom.GeometryFactory;
+import org.locationtech.jts.geom.LineString;
+import org.osgeo.proj4j.*;
+
+import java.util.List;
+
/**
* 坐标转换工具类。
*
@@ -104,4 +111,78 @@ public class CoordinateUtil {
return GCJ02ToBD(gcj02);
}
+ private static final CRSFactory crsFactory = new CRSFactory();
+
+ /**
+ * GCJ-02 → WGS84
+ * 输入的坐标点必须是GCJ-02坐标系的经纬度。
+ *
+ * @param lon 经度
+ * @param lat 纬度
+ * @return WGS84坐标
+ */
+ public static Double[] GCJ02ToWGS84(double lon, double lat) {
+ // 使用Proj4j进行坐标转换(需添加Proj4j依赖)
+ CoordinateReferenceSystem gcj02 = crsFactory.createFromName("EPSG:4490"); // 国家2000坐标系(近似GCJ-02)
+ CoordinateReferenceSystem wgs84 = crsFactory.createFromName("EPSG:4326");
+ CoordinateTransform transform = new CoordinateTransformFactory().createTransform(gcj02, wgs84);
+
+ ProjCoordinate src = new ProjCoordinate(lon, lat);
+ ProjCoordinate dst = new ProjCoordinate();
+ transform.transform(src, dst);
+ return new Double[]{dst.x, dst.y};
+ }
+
+ /**
+ * GCJ-02 → WGS84
+ * 输入的坐标点必须是GCJ-02坐标系的经纬度。
+ *
+ * @param lon 经度
+ * @param lat 纬度
+ * @return WGS84坐标
+ */
+ public static Coordinate gcj02ToWgs84(double lon, double lat) {
+ // 使用Proj4j进行坐标转换(需添加Proj4j依赖)
+ CoordinateReferenceSystem gcj02 = crsFactory.createFromName("EPSG:4490"); // 国家2000坐标系(近似GCJ-02)
+ CoordinateReferenceSystem wgs84 = crsFactory.createFromName("EPSG:4326");
+ CoordinateTransform transform = new CoordinateTransformFactory().createTransform(gcj02, wgs84);
+
+ ProjCoordinate src = new ProjCoordinate(lon, lat);
+ ProjCoordinate dst = new ProjCoordinate();
+ transform.transform(src, dst);
+ return new Coordinate(dst.x, dst.y);
+ }
+
+ private static final GeometryFactory geometryFactory = new GeometryFactory();
+
+ /**
+ * 计算路径总长度(单位:米)
+ * 输入的坐标点必须是WGS84坐标系的经纬度。
+ *
+ * @param points 坐标点列表,每个点为[经度, 纬度]
+ * @return 总长度(米)
+ */
+ public static Double calculateTotalDistance(List points) {
+ // 转换坐标并构建线串
+ LineString lineString = convertToLineString(points);
+
+ // 使用JTS计算几何距离(需确保坐标系为投影坐标系)
+ return lineString.getLength();
+ }
+
+ /**
+ * 转换坐标点列表为LineString
+ *
+ * @param points 坐标点列表
+ * @return LineString对象
+ */
+ private static LineString convertToLineString(List points) {
+ Coordinate[] coords = new Coordinate[points.size()];
+ for (int i = 0; i < points.size(); i++) {
+ Double[] p = points.get(i);
+ Coordinate wgs84Coord = gcj02ToWgs84(p[0], p[1]); // GCJ-02转WGS84
+ coords[i]= new Coordinate(wgs84Coord.x, wgs84Coord.y);
+ }
+ return geometryFactory.createLineString(coords);
+ }
}
diff --git a/ebike-feign/src/main/java/com/ebike/feign/clients/OperateFeignClient.java b/ebike-feign/src/main/java/com/ebike/feign/clients/OperateFeignClient.java
index b344286e..51ec82e2 100644
--- a/ebike-feign/src/main/java/com/ebike/feign/clients/OperateFeignClient.java
+++ b/ebike-feign/src/main/java/com/ebike/feign/clients/OperateFeignClient.java
@@ -4,6 +4,7 @@ import com.cdzy.common.model.EbikeTracking;
import com.cdzy.common.model.JsonResult;
import com.cdzy.common.model.ReqBatchRegionDto;
import com.ebike.feign.model.res.ReqEbikeSiteQuery;
+import com.ebike.feign.model.res.ReqEbikeTrackingDto;
import com.ebike.feign.model.res.ReqUserOperateDto;
import com.ebike.feign.model.res.ResFeignEbikeSysRcostsetDto;
import com.ebike.feign.model.rsp.FeignEbikeRegionDto;
@@ -69,6 +70,15 @@ public interface OperateFeignClient {
@PostMapping("ebikeTracking/save")
JsonResult> saveEbikeTracking(@RequestBody EbikeTracking ebikeTracking);
+ /**
+ * 车辆轨迹查询。
+ *
+ * @param reqEbikeTrackingDto 查询参数
+ * @return List
+ */
+ @PostMapping("ebikeTracking/query")
+ JsonResult> queryEbikeTracking(@RequestBody ReqEbikeTrackingDto reqEbikeTrackingDto);
+
/**
* 获取运营区详情。
*
diff --git a/ebike-operate/src/main/java/com/cdzy/ebikeoperate/model/dto/request/ReqEbikeTrackingDto.java b/ebike-feign/src/main/java/com/ebike/feign/model/res/ReqEbikeTrackingDto.java
similarity index 94%
rename from ebike-operate/src/main/java/com/cdzy/ebikeoperate/model/dto/request/ReqEbikeTrackingDto.java
rename to ebike-feign/src/main/java/com/ebike/feign/model/res/ReqEbikeTrackingDto.java
index a27abbdf..25b0677f 100644
--- a/ebike-operate/src/main/java/com/cdzy/ebikeoperate/model/dto/request/ReqEbikeTrackingDto.java
+++ b/ebike-feign/src/main/java/com/ebike/feign/model/res/ReqEbikeTrackingDto.java
@@ -1,4 +1,4 @@
-package com.cdzy.ebikeoperate.model.dto.request;
+package com.ebike.feign.model.res;
import jakarta.validation.constraints.NotBlank;
import lombok.AllArgsConstructor;
diff --git a/ebike-operate/src/main/java/com/cdzy/ebikeoperate/model/dto/response/EbikeTrackingDto.java b/ebike-feign/src/main/java/com/ebike/feign/model/rsp/EbikeTrackingDto.java
similarity index 85%
rename from ebike-operate/src/main/java/com/cdzy/ebikeoperate/model/dto/response/EbikeTrackingDto.java
rename to ebike-feign/src/main/java/com/ebike/feign/model/rsp/EbikeTrackingDto.java
index 24199fca..0a9fd0fa 100644
--- a/ebike-operate/src/main/java/com/cdzy/ebikeoperate/model/dto/response/EbikeTrackingDto.java
+++ b/ebike-feign/src/main/java/com/ebike/feign/model/rsp/EbikeTrackingDto.java
@@ -1,11 +1,15 @@
-package com.cdzy.ebikeoperate.model.dto.response;
+package com.ebike.feign.model.rsp;
+import lombok.AllArgsConstructor;
import lombok.Data;
+import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.time.LocalDateTime;
@Data
+@NoArgsConstructor
+@AllArgsConstructor
public class EbikeTrackingDto implements Serializable {
/**
diff --git a/ebike-gateway/src/main/resources/application-dev.yml b/ebike-gateway/src/main/resources/application-dev.yml
index 8aa4a4a4..e3bf31f3 100644
--- a/ebike-gateway/src/main/resources/application-dev.yml
+++ b/ebike-gateway/src/main/resources/application-dev.yml
@@ -52,6 +52,12 @@ spring:
- Path=/operate/**
filters:
- StripPrefix=1
+ - id: ebike-payment
+ uri: lb://ebike-payment
+ predicates:
+ - Path=/payment/**
+ filters:
+ - StripPrefix=1
data:
# redis配置
redis:
diff --git a/ebike-operate/src/main/java/com/cdzy/ebikeoperate/controller/EbikeTrackingController.java b/ebike-operate/src/main/java/com/cdzy/ebikeoperate/controller/EbikeTrackingController.java
index 496dbcc2..03f80060 100644
--- a/ebike-operate/src/main/java/com/cdzy/ebikeoperate/controller/EbikeTrackingController.java
+++ b/ebike-operate/src/main/java/com/cdzy/ebikeoperate/controller/EbikeTrackingController.java
@@ -6,8 +6,8 @@ import com.cdzy.ebikeoperate.model.pojo.EbikeSiteRegion;
import com.cdzy.ebikeoperate.service.EbikeSiteRegionService;
import com.cdzy.ebikeoperate.utils.RedisUtil;
import com.ebike.feign.model.res.ReqEbikeSiteQuery;
-import com.cdzy.ebikeoperate.model.dto.request.ReqEbikeTrackingDto;
-import com.cdzy.ebikeoperate.model.dto.response.EbikeTrackingDto;
+import com.ebike.feign.model.res.ReqEbikeTrackingDto;
+import com.ebike.feign.model.rsp.EbikeTrackingDto;
import com.cdzy.ebikeoperate.service.EbikeTrackingService;
import com.ebike.feign.model.rsp.EbikeSiteInfo;
import lombok.extern.slf4j.Slf4j;
diff --git a/ebike-operate/src/main/java/com/cdzy/ebikeoperate/service/EbikeTrackingService.java b/ebike-operate/src/main/java/com/cdzy/ebikeoperate/service/EbikeTrackingService.java
index aeeddb7b..231dbd6b 100644
--- a/ebike-operate/src/main/java/com/cdzy/ebikeoperate/service/EbikeTrackingService.java
+++ b/ebike-operate/src/main/java/com/cdzy/ebikeoperate/service/EbikeTrackingService.java
@@ -1,8 +1,8 @@
package com.cdzy.ebikeoperate.service;
import com.cdzy.common.model.EbikeTracking;
-import com.cdzy.ebikeoperate.model.dto.request.ReqEbikeTrackingDto;
-import com.cdzy.ebikeoperate.model.dto.response.EbikeTrackingDto;
+import com.ebike.feign.model.res.ReqEbikeTrackingDto;
+import com.ebike.feign.model.rsp.EbikeTrackingDto;
import java.util.List;
diff --git a/ebike-operate/src/main/java/com/cdzy/ebikeoperate/service/impl/EbikeTrackingServiceImpl.java b/ebike-operate/src/main/java/com/cdzy/ebikeoperate/service/impl/EbikeTrackingServiceImpl.java
index 61edab9b..aa437d97 100644
--- a/ebike-operate/src/main/java/com/cdzy/ebikeoperate/service/impl/EbikeTrackingServiceImpl.java
+++ b/ebike-operate/src/main/java/com/cdzy/ebikeoperate/service/impl/EbikeTrackingServiceImpl.java
@@ -4,10 +4,9 @@ import com.cdzy.common.model.EbikeTracking;
import com.cdzy.common.model.JsonResult;
import com.cdzy.common.utils.ConvertUtil;
import com.cdzy.ebikeoperate.model.dto.EbikeTrackingConfg;
-import com.cdzy.ebikeoperate.model.dto.request.ReqEbikeTrackingDto;
-import com.cdzy.ebikeoperate.model.dto.response.EbikeTrackingDto;
+import com.ebike.feign.model.res.ReqEbikeTrackingDto;
+import com.ebike.feign.model.rsp.EbikeTrackingDto;
import com.cdzy.ebikeoperate.service.EbikeTrackingService;
-import com.cdzy.common.utils.CoordinateUtil;
import com.ebike.feign.clients.MaintenanceFeignClient;
import com.influxdb.annotations.Measurement;
import com.influxdb.client.InfluxDBClient;
@@ -21,7 +20,6 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.time.*;
-import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.StringJoiner;
diff --git a/ebike-payment/src/main/java/com/cdzy/payment/config/GeoCodingConfig.java b/ebike-payment/src/main/java/com/cdzy/payment/config/GeoCodingConfig.java
new file mode 100644
index 00000000..f4f272fd
--- /dev/null
+++ b/ebike-payment/src/main/java/com/cdzy/payment/config/GeoCodingConfig.java
@@ -0,0 +1,22 @@
+package com.cdzy.payment.config;
+
+import com.cdzy.payment.utils.GeoCodingUtil;
+import lombok.Getter;
+import lombok.Setter;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Setter
+@Getter
+@Configuration
+@ConfigurationProperties(prefix = "geo-coding")
+public class GeoCodingConfig {
+ private String apiUrl;
+ private String accessKey;
+
+ @Bean
+ public GeoCodingUtil geoCodingUtil() {
+ return new GeoCodingUtil(apiUrl, accessKey);
+ }
+}
diff --git a/ebike-payment/src/main/java/com/cdzy/payment/service/EbikePaymentService.java b/ebike-payment/src/main/java/com/cdzy/payment/service/EbikePaymentService.java
index 2f00177e..b79cec7a 100644
--- a/ebike-payment/src/main/java/com/cdzy/payment/service/EbikePaymentService.java
+++ b/ebike-payment/src/main/java/com/cdzy/payment/service/EbikePaymentService.java
@@ -2,11 +2,13 @@ package com.cdzy.payment.service;
import com.cdzy.payment.model.dto.OrderDetailInfo;
import com.cdzy.payment.model.dto.ResOrderInfoDto;
+import com.cdzy.payment.model.dto.ResRefundOrderInfo;
import com.mybatisflex.core.service.IService;
import com.cdzy.payment.model.entity.EbikePayment;
import com.wechat.pay.java.service.payments.model.Transaction;
import java.util.List;
+import java.util.Map;
/**
* 用户订单支付记录 服务层。
@@ -53,5 +55,5 @@ public interface EbikePaymentService extends IService {
* @param orderId 退款id
* @return 订单详情
*/
- OrderDetailInfo getOrderDetail(String orderId);
+ Map getOrderDetail(String orderId);
}
diff --git a/ebike-payment/src/main/java/com/cdzy/payment/service/impl/EbikePaymentServiceImpl.java b/ebike-payment/src/main/java/com/cdzy/payment/service/impl/EbikePaymentServiceImpl.java
index 92c67e91..8c6fa2a3 100644
--- a/ebike-payment/src/main/java/com/cdzy/payment/service/impl/EbikePaymentServiceImpl.java
+++ b/ebike-payment/src/main/java/com/cdzy/payment/service/impl/EbikePaymentServiceImpl.java
@@ -1,11 +1,10 @@
package com.cdzy.payment.service.impl;
-import com.cdzy.payment.model.dto.OrderDetailInfo;
-import com.cdzy.payment.model.dto.ResOrderInfoDto;
import com.cdzy.payment.model.enums.PayMethod;
import com.cdzy.payment.utils.StringUtils;
import com.ebike.feign.clients.OrdersFeignClient;
import com.ebike.feign.model.res.ResFeignOrderPaymentDto;
+import com.mybatisflex.core.query.QueryMethods;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import com.cdzy.payment.model.entity.EbikePayment;
@@ -13,11 +12,15 @@ import com.cdzy.payment.mapper.EbikePaymentMapper;
import com.cdzy.payment.service.EbikePaymentService;
import com.wechat.pay.java.service.payments.model.Transaction;
import jakarta.annotation.Resource;
+import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.List;
+import java.util.Map;
import static com.cdzy.payment.model.entity.table.EbikePaymentTableDef.EBIKE_PAYMENT;
+import static com.cdzy.payment.model.entity.table.EbikeUserOrdersTableDef.EBIKE_USER_ORDERS;
+import static com.cdzy.payment.model.entity.table.EbikeUserTableDef.EBIKE_USER;
import static com.mybatisflex.core.constant.FuncName.*;
/**
@@ -26,6 +29,7 @@ import static com.mybatisflex.core.constant.FuncName.*;
* @author dingchao
* @since 2025-04-24
*/
+@Slf4j
@Service
public class EbikePaymentServiceImpl extends ServiceImpl implements EbikePaymentService{
@@ -84,10 +88,23 @@ public class EbikePaymentServiceImpl extends ServiceImpl orderDto.setDurationCost(orderDto.getDurationCost() + detailDto.getUnitPrice());
- case 2 ->
- orderDto.setDispatchFeeOutOperateArea(orderDto.getParkingAreaOutDispatchFee() + detailDto.getUnitPrice());
- case 3 ->
- orderDto.setParkingAreaOutDispatchFee(orderDto.getParkingAreaOutDispatchFee() + detailDto.getUnitPrice());
+ case 2 -> orderDto.setDispatchFeeOutOperateArea(orderDto.getParkingAreaOutDispatchFee() + detailDto.getUnitPrice());
+ case 3 -> orderDto.setParkingAreaOutDispatchFee(orderDto.getParkingAreaOutDispatchFee() + detailDto.getUnitPrice());
case 6 -> orderDto.setStartupCost(orderDto.getStartupCost() + detailDto.getUnitPrice());
}
}
@@ -600,7 +608,152 @@ public class WxPayServiceImpl implements WxPayService {
@Override
public ResRefundOrderInfo queryRefundApplyOrderById(String orderId) {
- return null;
+ Map recDetail = ebikePaymentService.getOrderDetail(orderId);
+ if (recDetail == null) {
+ log.error("{} 订单不存在", orderId);
+ return null;
+ }
+
+ ResRefundOrderInfo orderInfo = new ResRefundOrderInfo();
+ // 订单信息
+ OrderInfo order = new OrderInfo();
+ BeanUtils.copyProperties(recDetail, order);
+
+ // 用户信息
+ UserInfo userInfo = new UserInfo();
+ BeanUtils.copyProperties(recDetail, orderInfo);
+ orderInfo.setUserInfo(userInfo);
+ // 车辆基本信息
+ EbikeBikeBaseInfo bike = null;
+ JsonResult> bikeInfo = maintenanceFeignClient.getBikeBaseInfoByCode(order.getBikeCode());
+ if (bikeInfo.getCode() == Code.SUCCESS) {
+ bike = JSON.parseObject(JSONObject.toJSONString(bikeInfo.getData()), EbikeBikeBaseInfo.class);
+ }else {
+ log.error("获取车辆基本信息失败,车辆编码: {}", order.getBikeCode());
+ }
+
+ // 借用信息
+ BorrowingInfo borrowingInfo = new BorrowingInfo();
+ BeanUtils.copyProperties(recDetail, borrowingInfo);
+ Double[] borrowLocation = getBikeLocation(borrowingInfo.getBorrowCarCoordinate());
+ if (bike != null) {
+ if (borrowLocation != null) {
+ ReqEbikeSiteQuery siteQuery = new ReqEbikeSiteQuery();
+ siteQuery.setLatitude(borrowLocation[0]);
+ siteQuery.setLongitude(borrowLocation[1]);
+ siteQuery.setAreaId(Long.parseLong(bike.getReginId()));
+ JsonResult> siteInfo = operateFeignClient.querySite(siteQuery);
+ if (siteInfo.getCode() == Code.SUCCESS) {
+ EbikeSiteInfo site = JSON.parseObject(JSONObject.toJSONString(siteInfo.getData()), EbikeSiteInfo.class);
+ borrowingInfo.setBorrowSite(site.getSiteName());
+ }else {
+ log.error("获取车辆骑行站点信息失败,订单编号: {}", orderId);
+ }
+ }
+ }
+ // 借车地址
+ if(borrowLocation != null){
+ JSONObject location = new JSONObject();
+ location.put("lng", borrowLocation[0]);
+ location.put("lat", borrowLocation[1]);
+ JSONObject address = geoCodingUtil.getLocationToAddress(location);
+ if(address!= null){
+ borrowingInfo.setBorrowAddress(address.getString("detail"));
+ order.setStartRegion(address.getString("district"));
+ }
+ }
+ orderInfo.setBorrowingInfo(borrowingInfo);
+ // 还车信息
+ ReturnInfo returnInfo = new ReturnInfo();
+ BeanUtils.copyProperties(recDetail, returnInfo);
+ Double[] returnLocation = getBikeLocation(returnInfo.getReturnCarCoordinate());
+ if (bike != null) {
+ if (returnLocation != null) {
+ ReqEbikeSiteQuery siteQuery = new ReqEbikeSiteQuery();
+ siteQuery.setLatitude(returnLocation[0]);
+ siteQuery.setLongitude(returnLocation[1]);
+ siteQuery.setAreaId(Long.parseLong(bike.getReginId()));
+ JsonResult> siteInfo = operateFeignClient.querySite(siteQuery);
+ if (siteInfo.getCode() == Code.SUCCESS) {
+ EbikeSiteInfo site = JSON.parseObject(JSONObject.toJSONString(siteInfo.getData()), EbikeSiteInfo.class);
+ returnInfo.setReturnSite(site.getSiteName());
+ }else {
+ log.error("获取车辆还车站点信息失败,订单编号: {}", orderId);
+ }
+ }
+ }
+ // 还车地址
+ if(returnLocation != null){
+ JSONObject location = new JSONObject();
+ location.put("lng", returnLocation[0]);
+ location.put("lat", returnLocation[1]);
+ JSONObject address = geoCodingUtil.getLocationToAddress(location);
+ if(address!= null){
+ returnInfo.setReturnAddress(address.getString("detail"));
+ order.setEndRegion(address.getString("district"));
+ }
+ }
+ // 骑行时长
+ if (order.getUnLockTime() != null && order.getLockTime() != null) {
+ order.setCyclingDuration(String.valueOf(Duration.between(order.getUnLockTime(), order.getLockTime()).toMinutes()));
+ }
+ // 轨迹里程
+ if (order.getUnLockTime() != null && order.getLockTime() != null&& order.getBikeCode()!=null) {
+ ReqEbikeTrackingDto trackingDto = new ReqEbikeTrackingDto();
+ trackingDto.setEbikeCode(order.getBikeCode());
+ trackingDto.setStartTime(order.getUnLockTime());
+ trackingDto.setEndTime(order.getLockTime());
+ trackingDto.setInterval("30s");
+ JsonResult> tracking = operateFeignClient.queryEbikeTracking(trackingDto);
+ if (tracking.getCode() == Code.SUCCESS) {
+ List trackingList = JSON.parseArray(JSONObject.toJSONString(tracking.getData()), EbikeTrackingDto.class);
+ List trackingPoints = new ArrayList<>(trackingList.stream().map(t -> new Double[]{t.getLatitude(), t.getLongitude()}).toList());
+ if (borrowLocation!=null){
+ trackingPoints.add(0, borrowLocation);
+ }
+ if (returnLocation!=null){
+ trackingPoints.add(returnLocation);
+ }
+ Double distance = CoordinateUtil.calculateTotalDistance(trackingPoints);
+ if (distance > 1000) {
+ order.setTrajectoryMileage(String.format("%.3f公里", distance));
+ }else {
+ order.setTrajectoryMileage(String.format("%d米", Math.round(distance)));
+ }
+ }else {
+ log.error("获取车辆轨迹信息失败,订单编号: {}", orderId);
+ }
+
+ }
+ orderInfo.setOrderInfo(order);
+ orderInfo.setReturnInfo(returnInfo);
+
+ // 支付信息
+ PayInfo payInfo = new PayInfo();
+ BeanUtils.copyProperties(recDetail, payInfo);
+ orderInfo.setPayInfo(payInfo);
+ // 支付详情
+ OrderDetailInfo detailInfo = new OrderDetailInfo();
+ BeanUtils.copyProperties(recDetail, detailInfo);
+ detailInfo.setDiscountAmount(detailInfo.getTotalAmount() - detailInfo.getActualAmount());
+ //查询订单, orderFeingClient.getOrderById(orderId)
+ JsonResult> result = ordersFeignClient.getPaymentDetails(Long.valueOf(orderId));
+ if (result.getCode() != 200) {
+ EbikePaymentDto paymentDto = JSON.parseObject(JSONObject.toJSONString(result.getData()), EbikePaymentDto.class);
+ for (PayDetailDto detailDto : paymentDto.getDetail().getGoodsDetail()) {
+ //1-骑行时长费 2-运营区调度费用 3-停车区调度费用 4-高峰时段出行费用 5-高峰日出行费用 6-起步费用
+ switch (detailDto.getItemType()) {
+ case 1, 4, 5 -> detailInfo.setDurationCost(detailInfo.getDurationCost() + detailDto.getUnitPrice());
+ case 2 -> detailInfo.setDispatchFeeOutOperateArea(detailInfo.getParkingAreaOutDispatchFee() + detailDto.getUnitPrice());
+ case 3 -> detailInfo.setParkingAreaOutDispatchFee(detailInfo.getParkingAreaOutDispatchFee() + detailDto.getUnitPrice());
+ case 6 -> detailInfo.setStartupCost(detailInfo.getStartupCost() + detailDto.getUnitPrice());
+ }
+ }
+ }
+
+ orderInfo.setOrderDetailInfo(detailInfo);
+
+ return orderInfo;
}
@Override
@@ -609,6 +762,21 @@ public class WxPayServiceImpl implements WxPayService {
return null;
}
+
+ /**
+ * 获取车辆经纬度
+ *
+ * @param coordinate 坐标
+ * @return 经纬度
+ */
+ private Double[] getBikeLocation(String coordinate){
+ String[] split = coordinate.split(",");
+ if (split.length == 2) {
+ return new Double[]{Double.valueOf(split[0]), Double.valueOf(split[1])};
+ }
+ return null;
+ }
+
/**
* 打印日志
*
diff --git a/ebike-payment/src/main/java/com/cdzy/payment/utils/GeoCodingUtil.java b/ebike-payment/src/main/java/com/cdzy/payment/utils/GeoCodingUtil.java
new file mode 100644
index 00000000..4bfdf140
--- /dev/null
+++ b/ebike-payment/src/main/java/com/cdzy/payment/utils/GeoCodingUtil.java
@@ -0,0 +1,121 @@
+package com.cdzy.payment.utils;
+
+import com.alibaba.fastjson2.JSONObject;
+import lombok.extern.slf4j.Slf4j;
+import okhttp3.OkHttpClient;
+import okhttp3.Request;
+import okhttp3.Response;
+import org.springframework.stereotype.Service;
+
+import java.util.Arrays;
+
+/**
+ * 地址解析、反解析工具类。
+ *
+ * @author dingchao
+ * @date 2025/4/3
+ * @modified by:
+ */
+@Slf4j
+@Service
+public class GeoCodingUtil {
+ private final static String LOCATION_TO_ADDRESS = "location";
+ private final static String ADDRESS_TO_LOCATION = "address";
+
+ private final String url;
+ private final String accessKey;
+ private final OkHttpClient client;
+
+ /**
+ * 地理编码工具类构造函数。
+ * 目前实现的腾讯地图webservice
+ *
+ * @param apiUrl
+ * @param accessKey
+ */
+ public GeoCodingUtil(String apiUrl, String accessKey) {
+ this.url = apiUrl;
+ this.accessKey = accessKey;
+ this.client = new OkHttpClient();
+ }
+
+ /**
+ * 输入经纬度,返回地址。
+ *
+ * @param location 经纬度
+ * @return 地址
+ */
+ public JSONObject getLocationToAddress(JSONObject location) {
+ Request request = new Request.Builder()
+ .url(url + "/?"+LOCATION_TO_ADDRESS+"=" + String.format("%f,%f", location.getDouble("lat"), location.getDouble("lng")) + "&key=" + accessKey)
+ .build();
+ try(Response response = client.newCall(request).execute()) {
+ if(response.isSuccessful()) {
+ if (response.body()!= null) {
+ String result = response.body().string();
+ JSONObject jsonObject = JSONObject.parseObject(result);
+ if (jsonObject.getInteger("status") == 0) {
+ JSONObject address = new JSONObject();
+ String detail = jsonObject.getJSONObject("result").getJSONObject("formatted_addresses").getString("standard_address");
+ address.put("detail", detail);
+ String district = jsonObject.getJSONObject("result").getJSONObject("ad_info").getString("district");
+ address.put("district", district);
+ String adcode = jsonObject.getJSONObject("result").getJSONObject("ad_info").getString("adcode");
+ address.put("adcode", adcode);
+ return address;
+ }
+ logError("地址解析失败==>{}", jsonObject.getString("message"));
+ return null;
+ }
+ logError("地址解析失败==>{}", response.message());
+ return null;
+ }
+ logError("地址解析失败==>{}", response.message());
+ return null;
+ } catch (Exception e) {
+ logError("地址解析失败==>{}", e.getMessage() + Arrays.toString(e.getStackTrace()));
+ return null;
+ }
+ }
+
+
+ /**
+ * 输入地址,返回经纬度(GCJ02)。
+ *
+ * @param address 地址
+ * @return 经纬度
+ */
+ public JSONObject getAddressToLocation(String address) {
+ Request request = new Request.Builder()
+ .url(url + "/?"+ADDRESS_TO_LOCATION+"=" + address + "&key=" + accessKey)
+ .build();
+ try(Response response = client.newCall(request).execute()) {
+ if(response.isSuccessful()) {
+ if (response.body() != null) {
+ String result = response.body().string();
+ JSONObject jsonObject = JSONObject.parseObject(result);
+ if (jsonObject.getInteger("status") == 0) {
+ return jsonObject.getJSONObject("result").getJSONObject("location");
+ }else{
+ logError("位置解析失败==>{}", jsonObject.getString("message"));
+ return null;
+ }
+ }else{
+ logError("位置解析失败==>{}", response.message());
+ return null;
+ }
+ }else{
+ logError("位置解析失败==>{}", response.message());
+ return null;
+ }
+ } catch (Exception e) {
+ logError("位置解析失败==>{}", e.getMessage() + Arrays.toString(e.getStackTrace()));
+ return null;
+ }
+ }
+
+
+ private void logError(String errDesc, String errorMessage) {
+ log.error(errDesc, errorMessage);
+ }
+}
diff --git a/ebike-payment/src/main/resources/application-dev.yml b/ebike-payment/src/main/resources/application-dev.yml
index 406c966e..ba14885a 100644
--- a/ebike-payment/src/main/resources/application-dev.yml
+++ b/ebike-payment/src/main/resources/application-dev.yml
@@ -31,6 +31,22 @@ spring:
max-lifetime: 1800000
mybatis-flex:
mapper-locations: classpath:mapper/*.xml
+sa-token:
+ # token 名称(同时也是 cookie 名称)
+ token-name: Authorization
+ # token 有效期(单位:秒) 默认30天,-1 代表永久有效
+ timeout: 2592000
+ # token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结
+ active-timeout: -1
+ # 是否允许同一账号多地同时登录 (为 true 时允许一起登录, 为 false 时新登录挤掉旧登录)
+ is-concurrent: true
+ # 在多人登录同一账号时,是否共用一个 token (为 true 时所有登录共用一个 token, 为 false 时每次登录新建一个 token)
+ is-share: true
+ # token 风格(默认可取值:uuid、simple-uuid、random-32、random-64、random-128、tik)
+ token-style: random-32
+ # 是否输出操作日志
+ is-log: true
+
payment:
wx-pay:
app-id: wx327d788d7bd6eddf
@@ -50,18 +66,6 @@ task-scheduler-pool:
threadNamePrefix: task-scheduled-
waitForTasksToCompleteOnShutdown: true
awaitTerminationSeconds: 30
-sa-token:
- # token 名称(同时也是 cookie 名称)
- token-name: Authorization
- # token 有效期(单位:秒) 默认30天,-1 代表永久有效
- timeout: 2592000
- # token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结
- active-timeout: -1
- # 是否允许同一账号多地同时登录 (为 true 时允许一起登录, 为 false 时新登录挤掉旧登录)
- is-concurrent: true
- # 在多人登录同一账号时,是否共用一个 token (为 true 时所有登录共用一个 token, 为 false 时每次登录新建一个 token)
- is-share: true
- # token 风格(默认可取值:uuid、simple-uuid、random-32、random-64、random-128、tik)
- token-style: random-32
- # 是否输出操作日志
- is-log: true
\ No newline at end of file
+geo-coding:
+ api-url: https://apis.map.qq.com/ws/geocoder/v1
+ access-key: BECBZ-EJIEQ-LUU5N-B5ISQ-3TLMZ-BXFLG
\ No newline at end of file