修改退款申请订单详情中地址解析(含行政区划),轨迹里程计算实现
This commit is contained in:
parent
5b85cc252d
commit
31d929c99d
@ -37,6 +37,20 @@
|
||||
<artifactId>influxdb-client-java</artifactId>
|
||||
<version>6.10.0</version> <!-- 匹配InfluxDB 2.x版本 -->
|
||||
</dependency>
|
||||
|
||||
<!-- JTS 空间计算库 -->
|
||||
<dependency>
|
||||
<groupId>org.locationtech.jts</groupId>
|
||||
<artifactId>jts-core</artifactId>
|
||||
<version>1.19.0</version>
|
||||
</dependency>
|
||||
<!-- Proj4j坐标转换库 -->
|
||||
<dependency>
|
||||
<groupId>org.osgeo</groupId>
|
||||
<artifactId>proj4j</artifactId>
|
||||
<version>0.1.0</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
||||
@ -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<Double[]> points) {
|
||||
// 转换坐标并构建线串
|
||||
LineString lineString = convertToLineString(points);
|
||||
|
||||
// 使用JTS计算几何距离(需确保坐标系为投影坐标系)
|
||||
return lineString.getLength();
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换坐标点列表为LineString
|
||||
*
|
||||
* @param points 坐标点列表
|
||||
* @return LineString对象
|
||||
*/
|
||||
private static LineString convertToLineString(List<Double[]> 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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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<EbikeTrackingDto>
|
||||
*/
|
||||
@PostMapping("ebikeTracking/query")
|
||||
JsonResult<?> queryEbikeTracking(@RequestBody ReqEbikeTrackingDto reqEbikeTrackingDto);
|
||||
|
||||
/**
|
||||
* 获取运营区详情。
|
||||
*
|
||||
|
||||
@ -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;
|
||||
@ -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 {
|
||||
|
||||
/**
|
||||
@ -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:
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
@ -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<EbikePayment> {
|
||||
* @param orderId 退款id
|
||||
* @return 订单详情
|
||||
*/
|
||||
OrderDetailInfo getOrderDetail(String orderId);
|
||||
Map getOrderDetail(String orderId);
|
||||
}
|
||||
|
||||
@ -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<EbikePaymentMapper, EbikePayment> implements EbikePaymentService{
|
||||
|
||||
@ -84,10 +88,23 @@ public class EbikePaymentServiceImpl extends ServiceImpl<EbikePaymentMapper, Ebi
|
||||
}
|
||||
|
||||
@Override
|
||||
public OrderDetailInfo getOrderDetail(String orderId) {
|
||||
//QueryWrapper query = QueryWrapper.create()
|
||||
// .select(EBIKE_PAYMENT., EBIKE_PAYMENT.PAYMENT_ID, EBIKE_PAYMENT.TOTAL, EBIKE_PAYMENT.COST_PRICE, EBIKE_PAYMENT.CREATE_TIME, EBIKE_PAYMENT.TRADE_STATE)
|
||||
return null;
|
||||
public Map getOrderDetail(String orderId) {
|
||||
QueryWrapper query = QueryWrapper.create()
|
||||
.select(EBIKE_PAYMENT.COST_PRICE.as("totalAmount"), EBIKE_PAYMENT.TOTAL.as("actualAmount"),EBIKE_USER_ORDERS.BIKE_CODE.as("bikeCode"),
|
||||
EBIKE_USER_ORDERS.ORDER_ID.as("orderId"), EBIKE_USER_ORDERS.BIKE_CODE, EBIKE_USER_ORDERS.CREATED_AT.as("unLockTime"),
|
||||
EBIKE_USER_ORDERS.END_TIME.as("lockTime"), EBIKE_USER_ORDERS.CREATED_AT.as("createTime"),
|
||||
EBIKE_USER_ORDERS.END_TIME.as("endTime"), EBIKE_USER.NICKNAME.as("userName"), EBIKE_USER.MOBILE.as("phone"),
|
||||
EBIKE_USER_ORDERS.RIDE_POINT.as("borrowCarCoordinate"), EBIKE_USER_ORDERS.RETURN_POINT.as("returnCarCoordinate"),
|
||||
EBIKE_PAYMENT.PAYMENT_TIME.as("payTime"), QueryMethods.case_(EBIKE_PAYMENT.PAYMENT_METHOD)
|
||||
.when(PayMethod.wechat.name()).then("微信支付")
|
||||
.when(PayMethod.alipay.name()).then("支付宝")
|
||||
.when(PayMethod.balance.name()).then("余额").end().as("payMethod")
|
||||
)
|
||||
.leftJoin(EBIKE_USER_ORDERS).on(EBIKE_USER_ORDERS.ORDER_ID.eq(EBIKE_PAYMENT.ORDER_ID))
|
||||
.leftJoin(EBIKE_USER).on(EBIKE_USER.USER_ID.eq(EBIKE_USER_ORDERS.USER_ID))
|
||||
.where(EBIKE_PAYMENT.ORDER_ID.eq(orderId));
|
||||
return getOneAs(query, Map.class);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -2,7 +2,9 @@ package com.cdzy.payment.service.impl;
|
||||
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.cdzy.common.enums.Code;
|
||||
import com.cdzy.common.model.JsonResult;
|
||||
import com.cdzy.common.utils.CoordinateUtil;
|
||||
import com.cdzy.payment.config.WxPayConfig;
|
||||
import com.cdzy.payment.model.dto.*;
|
||||
import com.cdzy.payment.model.entity.EbikePayment;
|
||||
@ -13,15 +15,16 @@ import com.cdzy.payment.model.enums.RefundProcessState;
|
||||
import com.cdzy.payment.service.EbikePaymentService;
|
||||
import com.cdzy.payment.service.EbikeRefundService;
|
||||
import com.cdzy.payment.service.WxPayService;
|
||||
import com.cdzy.payment.utils.GeoCodingUtil;
|
||||
import com.cdzy.payment.utils.HttpServletUtils;
|
||||
import com.cdzy.payment.utils.StringUtils;
|
||||
import com.ebike.feign.clients.MaintenanceFeignClient;
|
||||
import com.ebike.feign.clients.OperateFeignClient;
|
||||
import com.ebike.feign.clients.OrdersFeignClient;
|
||||
import com.ebike.feign.model.rsp.AmountDto;
|
||||
import com.ebike.feign.model.rsp.DetailDto;
|
||||
import com.ebike.feign.model.rsp.EbikePaymentDto;
|
||||
import com.ebike.feign.model.rsp.PayDetailDto;
|
||||
import com.ebike.feign.model.res.ReqEbikeSiteQuery;
|
||||
import com.ebike.feign.model.res.ReqEbikeTrackingDto;
|
||||
import com.ebike.feign.model.rsp.*;
|
||||
import com.mybatisflex.core.paginate.Page;
|
||||
import com.mybatisflex.core.query.QueryWrapper;
|
||||
import com.wechat.pay.java.core.Config;
|
||||
import com.wechat.pay.java.core.cipher.Signer;
|
||||
import com.wechat.pay.java.core.exception.HttpException;
|
||||
@ -41,6 +44,7 @@ import com.wechat.pay.java.service.refund.model.*;
|
||||
import com.wechat.pay.java.service.payments.jsapi.JsapiService;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
@ -48,9 +52,8 @@ import java.math.BigDecimal;
|
||||
import java.time.*;
|
||||
import java.util.ArrayList;
|
||||
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.EbikeRefundTableDef.EBIKE_REFUND;
|
||||
import static com.wechat.pay.java.core.http.Constant.*;
|
||||
import static com.wechat.pay.java.core.http.Constant.WECHAT_PAY_SERIAL;
|
||||
|
||||
@ -81,6 +84,13 @@ public class WxPayServiceImpl implements WxPayService {
|
||||
private EbikeRefundService ebikeRefundService;
|
||||
@Resource
|
||||
private OrdersFeignClient ordersFeignClient;
|
||||
@Resource
|
||||
private MaintenanceFeignClient maintenanceFeignClient;
|
||||
@Resource
|
||||
private OperateFeignClient operateFeignClient;
|
||||
@Resource
|
||||
private GeoCodingUtil geoCodingUtil;
|
||||
|
||||
|
||||
@Override
|
||||
public boolean closeOrder(String outTradeNo) {
|
||||
@ -571,7 +581,7 @@ public class WxPayServiceImpl implements WxPayService {
|
||||
public ResOrderInfoDto queryRefundOrderById(String refundId) {
|
||||
ResOrderInfoDto orderDto = ebikeRefundService.getRefundOrderDetail(refundId);
|
||||
if (orderDto == null) {
|
||||
log.error("{}退款订单不存在", refundId);
|
||||
log.error("{} 退款订单不存在", refundId);
|
||||
return null;
|
||||
}
|
||||
//查询订单, orderFeingClient.getOrderById(orderId)
|
||||
@ -585,10 +595,8 @@ public class WxPayServiceImpl implements WxPayService {
|
||||
//1-骑行时长费 2-运营区调度费用 3-停车区调度费用 4-高峰时段出行费用 5-高峰日出行费用 6-起步费用
|
||||
switch (detailDto.getItemType()) {
|
||||
case 1, 4, 5 -> 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<EbikeTrackingDto> trackingList = JSON.parseArray(JSONObject.toJSONString(tracking.getData()), EbikeTrackingDto.class);
|
||||
List<Double[]> 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 打印日志
|
||||
*
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
@ -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
|
||||
geo-coding:
|
||||
api-url: https://apis.map.qq.com/ws/geocoder/v1
|
||||
access-key: BECBZ-EJIEQ-LUU5N-B5ISQ-3TLMZ-BXFLG
|
||||
Loading…
x
Reference in New Issue
Block a user