Compare commits
41 Commits
875ac87316
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 4fb1d9b00c | |||
| af71c55529 | |||
| d47caef111 | |||
| 09412ff8fe | |||
| d9be23b4cf | |||
| c730010937 | |||
| 540ecb522c | |||
| 1b7682729c | |||
| c8e1268e87 | |||
| 44508651b6 | |||
| fc29003411 | |||
| 362866113a | |||
| 18b9318b0d | |||
| 97444a1520 | |||
| b5c4e4226a | |||
| 3a0d707a5a | |||
| b3ba5ef5b1 | |||
| 53f98d9174 | |||
| a97513c33f | |||
| dab12a4b98 | |||
| d2ce1120b0 | |||
| 63bb831152 | |||
| f64bb390dc | |||
| 151898fdac | |||
| d627e9ed42 | |||
| 6aa0cb4834 | |||
| 79b0012d4e | |||
| 46fa58a78a | |||
| 1e95a147e6 | |||
| d9fe7405eb | |||
| 19a5bde9b0 | |||
| e2958b47ca | |||
| 9b85e3a39f | |||
| dd5603c450 | |||
| 7751595742 | |||
| 60defa3bb4 | |||
| 1f06e34d99 | |||
| 70a6b578ef | |||
| 5f56194f0c | |||
| b811e01da6 | |||
| 164434b3da |
59
pom.xml
59
pom.xml
@ -46,6 +46,11 @@
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
<artifactId>gson</artifactId>
|
||||
<version>2.13.2</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
@ -185,6 +190,12 @@
|
||||
<version>2.11.1</version> <!-- 可根据需要选择版本 -->
|
||||
</dependency>
|
||||
|
||||
<!-- Apache Commons Codec -->
|
||||
<dependency>
|
||||
<groupId>commons-codec</groupId>
|
||||
<artifactId>commons-codec</artifactId>
|
||||
<version>1.15</version>
|
||||
</dependency>
|
||||
<!-- swagger2 -->
|
||||
<dependency>
|
||||
<groupId>io.springfox</groupId>
|
||||
@ -243,8 +254,38 @@
|
||||
<artifactId>shedlock-provider-redis-spring</artifactId>
|
||||
<version>4.44.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.douyin.openapi</groupId>
|
||||
<artifactId>sdk</artifactId>
|
||||
<version>1.0.6</version>
|
||||
<scope>system</scope>
|
||||
<systemPath>${project.basedir}/src/main/resources/lib/sdk-1.0.6.jar</systemPath>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
<artifactId>gson</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.meituan.sdk</groupId>
|
||||
<artifactId>sdk</artifactId>
|
||||
<version>1.0</version>
|
||||
<scope>system</scope>
|
||||
<systemPath>${project.basedir}/src/main/resources/lib/MtOpJavaSDK-1.0-SNAPSHOT.jar</systemPath>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
<artifactId>gson</artifactId>
|
||||
<version>2.13.2</version> <!-- 或更高稳定版本 -->
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<!-- Build Configuration -->
|
||||
<build>
|
||||
<finalName>sczx_order</finalName>
|
||||
@ -262,6 +303,19 @@
|
||||
<exclude>*.yml</exclude>
|
||||
</excludes>
|
||||
</resource>
|
||||
<resource>
|
||||
<directory>src/main/resources</directory>
|
||||
<includes>
|
||||
<include>lib/*.jar</include>
|
||||
</includes>
|
||||
<targetPath>${project.build.directory}/lib</targetPath>
|
||||
</resource>
|
||||
<resource>
|
||||
<directory>src/main/resources</directory>
|
||||
<excludes>
|
||||
<exclude>lib/**</exclude>
|
||||
</excludes>
|
||||
</resource>
|
||||
</resources>
|
||||
<plugins>
|
||||
<!-- Compiler Plugin -->
|
||||
@ -278,6 +332,10 @@
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<configuration>
|
||||
<!-- 确保包含系统作用域的依赖 -->
|
||||
<includeSystemScope>true</includeSystemScope>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
@ -297,6 +355,7 @@
|
||||
<skip>true</skip>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
|
||||
@ -7,4 +7,6 @@ public interface RedisKeyConstants {
|
||||
|
||||
String BIND_CAR_KEY = SERVICE_PREFIX + "bindCar:";
|
||||
|
||||
String E_Fence_KEY = SERVICE_PREFIX + "eFence:";
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,20 @@
|
||||
package com.sczx.order.common.enums;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* @Author: 张黎
|
||||
* @Date: 2024/03/08/17:42
|
||||
* @Description: 支付方式枚举
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
public enum CouponTypeEnum {
|
||||
MT("MT", "美团"),
|
||||
DY("DY", "抖音"),
|
||||
;
|
||||
private final String code;
|
||||
|
||||
private final String msg;
|
||||
}
|
||||
103
src/main/java/com/sczx/order/config/DouyinTokenManager.java
Normal file
103
src/main/java/com/sczx/order/config/DouyinTokenManager.java
Normal file
@ -0,0 +1,103 @@
|
||||
package com.sczx.order.config;
|
||||
|
||||
import com.aliyun.tea.TeaException;
|
||||
import com.douyin.openapi.client.Client;
|
||||
import com.douyin.openapi.client.models.OauthClientTokenRequest;
|
||||
import com.douyin.openapi.client.models.OauthClientTokenResponse;
|
||||
import com.douyin.openapi.credential.models.Config;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import java.util.concurrent.ScheduledThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
/**
|
||||
* 抖音 client_token 管理器
|
||||
* 负责定时获取和缓存 client_token
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
public class DouyinTokenManager {
|
||||
|
||||
// 应用凭证信息
|
||||
@Value("${coupon.douyin.client_key}")
|
||||
private String CLIENT_KEY;
|
||||
|
||||
@Value("${coupon.douyin.client_secret}")
|
||||
private String CLIENT_SECRET;
|
||||
|
||||
// Token 缓存
|
||||
private final AtomicReference<OauthClientTokenResponse> tokenCache =
|
||||
new AtomicReference<>();
|
||||
|
||||
// 定时任务执行器
|
||||
private final ScheduledThreadPoolExecutor scheduler =
|
||||
new ScheduledThreadPoolExecutor(1, r -> {
|
||||
Thread t = new Thread(r, "DouyinTokenRefreshThread");
|
||||
t.setDaemon(false);
|
||||
return t;
|
||||
});
|
||||
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
// 初始化时立即获取一次 token
|
||||
refreshClientToken();
|
||||
|
||||
// 每小时更新一次 token (3600秒)
|
||||
scheduler.scheduleAtFixedRate(
|
||||
this::refreshClientToken,
|
||||
3600,
|
||||
3600,
|
||||
TimeUnit.SECONDS
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前有效的 client_token
|
||||
*
|
||||
* @return 当前有效的 access_token
|
||||
*/
|
||||
public String getCurrentToken() {
|
||||
OauthClientTokenResponse response = tokenCache.get();
|
||||
if (response != null && response.getData() != null) {
|
||||
return response.getData().getAccessToken();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 刷新 client_token
|
||||
*/
|
||||
private void refreshClientToken() {
|
||||
try {
|
||||
Config config = new Config()
|
||||
.setClientKey(CLIENT_KEY)
|
||||
.setClientSecret(CLIENT_SECRET);
|
||||
|
||||
Client client = new Client(config);
|
||||
|
||||
OauthClientTokenRequest sdkRequest = new OauthClientTokenRequest();
|
||||
sdkRequest.setClientKey(CLIENT_KEY);
|
||||
sdkRequest.setClientSecret(CLIENT_SECRET);
|
||||
sdkRequest.setGrantType("client_credential");
|
||||
|
||||
OauthClientTokenResponse sdkResponse = client.OauthClientToken(sdkRequest);
|
||||
|
||||
// 更新缓存
|
||||
tokenCache.set(sdkResponse);
|
||||
|
||||
if (sdkResponse.getData() != null) {
|
||||
log.info("抖音 client_token 更新成功: {},有效期至: {}", sdkResponse.getData().getAccessToken(),
|
||||
(System.currentTimeMillis() + sdkResponse.getData().getExpiresIn() * 1000));
|
||||
}
|
||||
} catch (TeaException e) {
|
||||
log.error("获取抖音 client_token 失败 (TeaException): " + e.getMessage());
|
||||
} catch (Exception e) {
|
||||
log.error("获取抖音 client_token 失败 (Exception): " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -65,6 +65,12 @@ public class ClientOrderController {
|
||||
return Result.ok(orderService.depositFreePayRentCarOrder(rentCarOrderReq));
|
||||
}
|
||||
|
||||
@ApiOperation(value = "第三方订单")
|
||||
@PostMapping("/thirdPlatformRentCarOrder")
|
||||
public Result<RentCarOrderResultDTO> thirdPlatformRentCarOrder(@Valid @RequestBody RentCarThirdPlatformOrderReq rentCarOrderReq){
|
||||
return Result.ok(orderService.thirdPlatformRentCarOrder(rentCarOrderReq));
|
||||
}
|
||||
|
||||
@ApiOperation(value = "续租车")
|
||||
@PostMapping("/reRentalCarOrder")
|
||||
public Result<RentCarOrderResultDTO> reRentalCarOrder(@Valid @RequestBody ReRentCarReq rentCarOrderReq){
|
||||
|
||||
@ -2,6 +2,7 @@ package com.sczx.order.controller;
|
||||
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.sczx.order.common.Result;
|
||||
import com.sczx.order.dto.VerifyGroupBuyCouponsReq;
|
||||
import com.sczx.order.dto.OrderDetailDTO;
|
||||
import com.sczx.order.dto.OrderDistribDTO;
|
||||
import com.sczx.order.dto.OrderDistribQueryReq;
|
||||
@ -12,6 +13,8 @@ import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.validation.Valid;
|
||||
|
||||
/**
|
||||
* @Author: 张黎
|
||||
* @Date: 2025/07/25/16:42
|
||||
@ -49,4 +52,10 @@ public class PubOrderController {
|
||||
orderDistribService.saveOrderDistrib(orderNo);
|
||||
return Result.ok(true);
|
||||
}
|
||||
|
||||
@ApiOperation(value = "团购券核销")
|
||||
@PostMapping("/verifyGroupBuyCoupons")
|
||||
public Result<OrderDetailDTO> verifyGroupBuyCoupons(@Valid @RequestBody VerifyGroupBuyCouponsReq req){
|
||||
return Result.ok(orderService.verifyGroupBuyCoupons( req));
|
||||
}
|
||||
}
|
||||
|
||||
@ -60,4 +60,10 @@ public class StoreOrderController {
|
||||
public Result<OrderDTO> confirmReturnCar(@RequestBody ReturnCarReq returnCarReq){
|
||||
return Result.ok(orderService.confirmReturnCar(returnCarReq));
|
||||
}
|
||||
|
||||
@ApiOperation(value = "抖音团购核销")
|
||||
@PostMapping("/verifyCar")
|
||||
public Result<OrderDTO> verifyCar(@RequestBody ReturnCarReq returnCarReq){
|
||||
return Result.ok(orderService.confirmReturnCar(returnCarReq));
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,35 @@
|
||||
package com.sczx.order.controller;
|
||||
|
||||
import com.sczx.order.common.Result;
|
||||
import com.sczx.order.service.DouyinService;
|
||||
import com.sczx.order.service.MeiTuanService;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequestMapping("/verify")
|
||||
public class VerifyController {
|
||||
|
||||
@Autowired
|
||||
private MeiTuanService meituanService;
|
||||
|
||||
@ApiOperation(value = "接收美团Token数据接口")
|
||||
@GetMapping("/authorization")
|
||||
public Result<String> authorization(@RequestParam("code") String code, @RequestParam("sign") String sign, @RequestParam("developerId") Long developerId, @RequestParam("businessId") int businessId,
|
||||
@RequestParam("state") String state){
|
||||
|
||||
log.info("接收美团授权数据 - code: {}, sign: {}, developerId: {}, businessId: {}, state: {}",
|
||||
code, sign, developerId, businessId, state);
|
||||
|
||||
return Result.ok(meituanService.getAccessToken(code,state));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -1,9 +1,6 @@
|
||||
package com.sczx.order.convert;
|
||||
|
||||
import com.sczx.order.dto.OrderDTO;
|
||||
import com.sczx.order.dto.OrderDetailDTO;
|
||||
import com.sczx.order.dto.RentCarOrderReq;
|
||||
import com.sczx.order.dto.SimpleUserInfoDTO;
|
||||
import com.sczx.order.dto.*;
|
||||
import com.sczx.order.po.OrderMainPO;
|
||||
import com.sczx.order.po.OrderSubPO;
|
||||
import com.sczx.order.thirdpart.dto.*;
|
||||
@ -46,6 +43,31 @@ public interface OrderConvert {
|
||||
})
|
||||
OrderMainPO subOrderToPo(RentCarOrderReq rentCarOrderReq, SimpleUserInfoDTO userInfoDTO, RentCarRuleDTO rentCarRuleDTO);
|
||||
|
||||
@Mappings({
|
||||
@Mapping(target = "orderId", ignore = true),
|
||||
@Mapping(target = "createTime", ignore = true),
|
||||
@Mapping(target = "updateTime", ignore = true),
|
||||
@Mapping(target = "delFlag", ignore = true),
|
||||
@Mapping(source = "rentCarOrderReq.storeId", target = "storeId"),
|
||||
@Mapping(source = "rentCarOrderReq.operatorId", target = "operatorId"),
|
||||
@Mapping(source = "rentCarOrderReq.carModelId", target = "carModelId"),
|
||||
@Mapping(source = "rentCarOrderReq.rentCarRuleId", target = "rentCarRuleId"),
|
||||
@Mapping(source = "rentCarOrderReq.rentBatteyRuleId", target = "rentBatteyRuleId"),
|
||||
@Mapping(source = "rentCarOrderReq.isDepositFree", target = "isDepositFree"),
|
||||
@Mapping(source = "rentCarOrderReq.batteryType", target = "batteryType"),
|
||||
@Mapping(source = "userInfoDTO.userId", target = "customerId"),
|
||||
@Mapping(source = "userInfoDTO.userName", target = "customerName"),
|
||||
@Mapping(source = "userInfoDTO.phoneNumber", target = "customerPhone"),
|
||||
@Mapping(source = "rentCarRuleDTO.rentalType", target = "rentalType"),
|
||||
@Mapping(source = "rentCarRuleDTO.rentalDays", target = "rentalDays"),
|
||||
@Mapping(source = "rentCarRuleDTO.rentalPrice", target = "rentalPrice"),
|
||||
@Mapping(source = "rentCarRuleDTO.depositPrice", target = "depositPrice"),
|
||||
@Mapping(source = "rentCarRuleDTO.overdueFee", target = "overdueFee"),
|
||||
@Mapping(source = "rentCarRuleDTO.overdueType", target = "overdueType")
|
||||
|
||||
})
|
||||
OrderMainPO subOrderToPo(RentCarThirdPlatformOrderReq rentCarOrderReq, SimpleUserInfoDTO userInfoDTO, RentCarRuleDTO rentCarRuleDTO);
|
||||
|
||||
@Mappings({
|
||||
|
||||
@Mapping(source = "orderMainPO.orderId", target = "orderId"),
|
||||
|
||||
38
src/main/java/com/sczx/order/dto/GroupBuyOrderInfoDto.java
Normal file
38
src/main/java/com/sczx/order/dto/GroupBuyOrderInfoDto.java
Normal file
@ -0,0 +1,38 @@
|
||||
package com.sczx.order.dto;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
/**
|
||||
* 团购订单必须信息
|
||||
* @Author: 张黎
|
||||
* @Date: 2025/10/27/20:42
|
||||
* @Description:
|
||||
*/
|
||||
@Data
|
||||
public class GroupBuyOrderInfoDto {
|
||||
|
||||
@ApiModelProperty(value = "门店id")
|
||||
@NotNull(message = "门店id不能为空")
|
||||
private Long storeId;
|
||||
|
||||
@ApiModelProperty(value = "客户id")
|
||||
private Long customerId;
|
||||
|
||||
@ApiModelProperty("车型ID")
|
||||
@NotNull(message = "车型ID不能为空")
|
||||
private Long carModelId;
|
||||
|
||||
@ApiModelProperty(value = "租车套餐id")
|
||||
@NotNull(message = "租车套餐id不能为空")
|
||||
private Long rentCarRuleId;
|
||||
|
||||
|
||||
@ApiModelProperty(value = "租电套餐id")
|
||||
private Long rentBatteyRuleId;
|
||||
|
||||
@ApiModelProperty(value = "团购券类型")
|
||||
private String couponType;
|
||||
}
|
||||
@ -0,0 +1,62 @@
|
||||
package com.sczx.order.dto;
|
||||
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
/**
|
||||
* @Author: 张黎
|
||||
* @Date: 2025/07/25/16:58
|
||||
* @Description:
|
||||
*/
|
||||
@Data
|
||||
@ApiModel(value = "租车订单请求参数")
|
||||
public class RentCarThirdPlatformOrderReq {
|
||||
|
||||
@ApiModelProperty(value = "订单编号,租车不需要传,续租和逾期处理需要传")
|
||||
private String orderNo;
|
||||
|
||||
@ApiModelProperty(value = "运营商id")
|
||||
private Long operatorId;
|
||||
|
||||
@ApiModelProperty(value = "门店id")
|
||||
@NotNull(message = "门店id不能为空")
|
||||
private Long storeId;
|
||||
|
||||
@ApiModelProperty(value = "客户id")
|
||||
private Long customerId;
|
||||
|
||||
@ApiModelProperty(value = "客户姓名")
|
||||
private String customerName;
|
||||
|
||||
@ApiModelProperty(value = "客户电话")
|
||||
private String customerPhone;
|
||||
|
||||
@ApiModelProperty(value = "第三方订单号")
|
||||
private String thirdOrderNo;
|
||||
|
||||
@ApiModelProperty(value = "订单来源")
|
||||
private String orderSource;
|
||||
|
||||
@ApiModelProperty("车型ID")
|
||||
@NotNull(message = "车型ID不能为空")
|
||||
private Long carModelId;
|
||||
|
||||
@ApiModelProperty(value = "租车套餐id")
|
||||
@NotNull(message = "租车套餐id不能为空")
|
||||
private Long rentCarRuleId;
|
||||
|
||||
|
||||
@ApiModelProperty(value = "租电套餐id")
|
||||
private Long rentBatteyRuleId;
|
||||
|
||||
@ApiModelProperty("选择的电池类型")
|
||||
private String batteryType;
|
||||
|
||||
|
||||
@ApiModelProperty("是否开通免押")
|
||||
private Boolean isDepositFree = false;
|
||||
}
|
||||
@ -0,0 +1,34 @@
|
||||
package com.sczx.order.dto;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
/**
|
||||
* @Author: 张黎
|
||||
* @Date: 2025/10/27/19:13
|
||||
* @Description:
|
||||
*/
|
||||
@ApiModel(value = "团购券核销请求参数")
|
||||
@Data
|
||||
public class VerifyGroupBuyCouponsReq {
|
||||
|
||||
@NotEmpty(message = "券码类型不能为空")
|
||||
@ApiModelProperty(value = "券码类型:美团MT,抖音DY")
|
||||
private String couponType;
|
||||
|
||||
@NotEmpty(message = "券码不能为空")
|
||||
@ApiModelProperty(value = "券码")
|
||||
private String couponCode;
|
||||
|
||||
@NotNull(message = "门店id不能为空")
|
||||
@ApiModelProperty(value = "门店id")
|
||||
private Long storeId;
|
||||
|
||||
@NotEmpty(message = "用户手机号不能为空")
|
||||
@ApiModelProperty(value = "用户完整手机号")
|
||||
private String mobile;
|
||||
}
|
||||
@ -0,0 +1,17 @@
|
||||
package com.sczx.order.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.sczx.order.po.ElectronicFenceRulePO;
|
||||
import com.sczx.order.po.OrderCarChangePO;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 订单车辆变更表 Mapper 接口
|
||||
* </p>
|
||||
*
|
||||
* @author zhangli
|
||||
* @since 2025-09-03 23:12:55
|
||||
*/
|
||||
public interface ElectronicFenceRuleMapper extends BaseMapper<ElectronicFenceRulePO> {
|
||||
|
||||
}
|
||||
66
src/main/java/com/sczx/order/po/ElectronicFenceRulePO.java
Normal file
66
src/main/java/com/sczx/order/po/ElectronicFenceRulePO.java
Normal file
@ -0,0 +1,66 @@
|
||||
package com.sczx.order.po;
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 套餐规则与电子围栏关联表
|
||||
* </p>
|
||||
*
|
||||
* @author lingma
|
||||
* @since 2025-07-25 17:17:28
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@TableName("zc_electronic_fence_rule")
|
||||
@ApiModel(value = "ElectronicFenceRulePO对象", description = "套餐规则与电子围栏关联表")
|
||||
public class ElectronicFenceRulePO implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@ApiModelProperty("规则ID")
|
||||
@TableId(value = "id", type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
@ApiModelProperty("车辆规则ID")
|
||||
private Long carRuleId;
|
||||
|
||||
@ApiModelProperty("电子围栏ID")
|
||||
private Long electronicFenceId;
|
||||
|
||||
@ApiModelProperty("排序")
|
||||
private Integer sortOrder;
|
||||
|
||||
@ApiModelProperty("删除标志(0代表存在 2代表删除)")
|
||||
private String delFlag;
|
||||
|
||||
@ApiModelProperty("创建者")
|
||||
private String createBy;
|
||||
|
||||
@JSONField(format = "yyyy-MM-dd HH:mm:ss")
|
||||
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
@ApiModelProperty("创建时间")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
@ApiModelProperty("更新者")
|
||||
private String updateBy;
|
||||
|
||||
@JSONField(format = "yyyy-MM-dd HH:mm:ss")
|
||||
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||
@ApiModelProperty("更新时间")
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
@ApiModelProperty("备注")
|
||||
private String remark;
|
||||
}
|
||||
@ -0,0 +1,16 @@
|
||||
package com.sczx.order.repository;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.sczx.order.po.ElectronicFenceRulePO;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 套餐规则与电子围栏关联表 服务类
|
||||
* </p>
|
||||
*
|
||||
* @author lingma
|
||||
* @since 2025-07-25 17:17:28
|
||||
*/
|
||||
public interface ElectronicFenceRuleRepo extends IService<ElectronicFenceRulePO> {
|
||||
|
||||
}
|
||||
@ -0,0 +1,21 @@
|
||||
package com.sczx.order.repository.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.sczx.order.po.ElectronicFenceRulePO;
|
||||
import com.sczx.order.repository.ElectronicFenceRuleRepo;
|
||||
import com.sczx.order.mapper.ElectronicFenceRuleMapper;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 套餐规则与电子围栏关联表 服务实现类
|
||||
* </p>
|
||||
*
|
||||
* @author lingma
|
||||
* @since 2025-07-25 17:17:28
|
||||
*/
|
||||
@Service
|
||||
public class ElectronicFenceRuleRepoImpl extends ServiceImpl<ElectronicFenceRuleMapper, ElectronicFenceRulePO> implements ElectronicFenceRuleRepo {
|
||||
|
||||
}
|
||||
17
src/main/java/com/sczx/order/service/DouyinService.java
Normal file
17
src/main/java/com/sczx/order/service/DouyinService.java
Normal file
@ -0,0 +1,17 @@
|
||||
package com.sczx.order.service;
|
||||
|
||||
import com.douyin.openapi.client.models.*;
|
||||
|
||||
|
||||
public interface DouyinService {
|
||||
|
||||
CertificatePrepareResponse prepare(CertificatePrepareRequest req);
|
||||
|
||||
CertificateVerifyResponse verify(CertificateVerifyRequest req);
|
||||
|
||||
CertificateCancelResponse cancel(CertificateCancelRequest req);
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,27 @@
|
||||
package com.sczx.order.service;
|
||||
|
||||
import com.sczx.order.dto.GroupBuyOrderInfoDto;
|
||||
|
||||
/** 团购券服务
|
||||
* @Author: 张黎
|
||||
* @Date: 2025/10/27/20:30
|
||||
* @Description:
|
||||
*/
|
||||
public interface GroupBuyCouponService {
|
||||
/**
|
||||
* 获取团购券下单信息
|
||||
* @param couponCode 团购券码
|
||||
* @param couponType 团购券类型
|
||||
* @param mobile 手机号
|
||||
* @return
|
||||
*/
|
||||
GroupBuyOrderInfoDto getGroupBuyOrderInfoDto(String couponCode, String couponType, String mobile);
|
||||
|
||||
/**
|
||||
* 校验团购券码
|
||||
* @param couponCode 团购券码
|
||||
* @param couponType 团购券类型
|
||||
* @return
|
||||
*/
|
||||
boolean checkCouponCode(String couponCode, String couponType);
|
||||
}
|
||||
17
src/main/java/com/sczx/order/service/MeiTuanService.java
Normal file
17
src/main/java/com/sczx/order/service/MeiTuanService.java
Normal file
@ -0,0 +1,17 @@
|
||||
package com.sczx.order.service;
|
||||
|
||||
import com.meituan.sdk.MeituanResponse;
|
||||
import com.meituan.sdk.auth.MeituanTokenResponse;
|
||||
import com.meituan.sdk.model.ddzh.tuangou.tuangouReceiptConsume.TuangouReceiptConsumeResponse;
|
||||
|
||||
public interface MeiTuanService {
|
||||
|
||||
MeituanTokenResponse getAccessToken(String code , String state);
|
||||
|
||||
MeituanTokenResponse prepare(String code);
|
||||
|
||||
MeituanResponse<TuangouReceiptConsumeResponse> consume(String code);
|
||||
|
||||
MeituanTokenResponse refreshAccessToken(String refreshToken);
|
||||
|
||||
}
|
||||
@ -15,6 +15,13 @@ public interface OrderService {
|
||||
*/
|
||||
OrderMainPO queryOrderMainPoByOrderNo(String orderNo, String delFlag);
|
||||
|
||||
/**
|
||||
* 团购券核销
|
||||
* @param req
|
||||
* @return
|
||||
*/
|
||||
OrderDetailDTO verifyGroupBuyCoupons(VerifyGroupBuyCouponsReq req) ;
|
||||
|
||||
/**
|
||||
* 提交租车订单
|
||||
* @param rentCarOrderReq
|
||||
@ -36,6 +43,14 @@ public interface OrderService {
|
||||
*/
|
||||
RentCarOrderResultDTO depositFreePayRentCarOrder(RentCarOrderReq rentCarOrderReq);
|
||||
|
||||
|
||||
/**
|
||||
* 第三方订单
|
||||
* @param rentCarOrderReq
|
||||
* @return
|
||||
*/
|
||||
RentCarOrderResultDTO thirdPlatformRentCarOrder(RentCarThirdPlatformOrderReq rentCarOrderReq);
|
||||
|
||||
/**
|
||||
* 续租车
|
||||
* @param rentCarOrderReq
|
||||
|
||||
@ -7,6 +7,8 @@ import java.math.BigDecimal;
|
||||
|
||||
public interface PayService {
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 预支付下单
|
||||
* @param payType
|
||||
@ -30,6 +32,19 @@ public interface PayService {
|
||||
String refundOrder(String payType,Long companyId,String outTradeNo, BigDecimal totalFee, BigDecimal refundFee);
|
||||
|
||||
|
||||
/**
|
||||
* 支付宝免押扣款
|
||||
* @param body
|
||||
* @param companyId
|
||||
* @param outTradeNo
|
||||
* @param authNo
|
||||
* @param aliPayOpenId
|
||||
* @param totalFee
|
||||
* @return
|
||||
*/
|
||||
UnifiedPaymentInfoDTO zhimaPayOrder(String body, Long companyId, String outTradeNo, String authNo, String aliPayOpenId,BigDecimal totalFee);
|
||||
|
||||
|
||||
/**
|
||||
* 冻结
|
||||
* @param companyId
|
||||
@ -46,7 +61,7 @@ public interface PayService {
|
||||
* @param authCode
|
||||
* @return
|
||||
*/
|
||||
boolean finishFreezeOrder(Long companyId,String outOrderNo, String authCode);
|
||||
boolean finishFreezeOrder(Long companyId,String outOrderNo, String authCode, BigDecimal freezeFee);
|
||||
|
||||
/**
|
||||
* 取消冻结
|
||||
|
||||
191
src/main/java/com/sczx/order/service/impl/DouyinServiceImpl.java
Normal file
191
src/main/java/com/sczx/order/service/impl/DouyinServiceImpl.java
Normal file
@ -0,0 +1,191 @@
|
||||
package com.sczx.order.service.impl;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.aliyun.tea.TeaException;
|
||||
import com.douyin.openapi.client.Client;
|
||||
import com.douyin.openapi.client.models.*;
|
||||
import com.douyin.openapi.credential.models.Config;
|
||||
|
||||
|
||||
import com.meituan.sdk.DefaultMeituanClient;
|
||||
import com.meituan.sdk.MeituanClient;
|
||||
import com.meituan.sdk.MeituanResponse;
|
||||
import com.meituan.sdk.auth.MeituanTokenResponse;
|
||||
import com.meituan.sdk.internal.utils.SignerUtil;
|
||||
import com.meituan.sdk.model.ddzh.tuangou.tuangouReceiptPrepare.TuangouReceiptPrepareRequest;
|
||||
import com.meituan.sdk.model.ddzh.tuangou.tuangouReceiptPrepare.TuangouReceiptPrepareResponse;
|
||||
import com.sczx.order.common.Result;
|
||||
import com.sczx.order.config.DouyinTokenManager;
|
||||
import com.sczx.order.dto.VerifyGroupBuyCouponsReq;
|
||||
import com.sczx.order.exception.InnerException;
|
||||
import com.sczx.order.service.DouyinService;
|
||||
import com.sczx.order.thirdpart.dto.CompanyStoreDTO;
|
||||
import com.sczx.order.thirdpart.integration.StoreInteg;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
public class DouyinServiceImpl implements DouyinService {
|
||||
|
||||
@Value("${coupon.douyin.client_key}")
|
||||
private String CLIENT_KEY;
|
||||
|
||||
@Value("${coupon.douyin.client_secret}")
|
||||
private String CLIENT_SECRET;
|
||||
|
||||
@Value("${coupon.douyin.account_id}")
|
||||
private String ACCOUNT_ID;
|
||||
|
||||
@Value("${coupon.douyin.poi_id}")
|
||||
private String POI_ID;
|
||||
|
||||
@Autowired
|
||||
private DouyinTokenManager douyinTokenManager;
|
||||
|
||||
|
||||
public String resolveShortUrlToGetObjectId(String shortUrl) {
|
||||
try {
|
||||
URL url = new URL(shortUrl);
|
||||
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
|
||||
connection.setInstanceFollowRedirects(false); // 禁止自动重定向
|
||||
connection.connect();
|
||||
|
||||
String longUrl = connection.getHeaderField("Location");
|
||||
connection.disconnect();
|
||||
|
||||
if (longUrl == null || longUrl.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// 使用正则表达式匹配object_id参数
|
||||
java.util.regex.Pattern pattern = java.util.regex.Pattern.compile("object_id=([^&]*)");
|
||||
java.util.regex.Matcher matcher = pattern.matcher(longUrl);
|
||||
|
||||
if (matcher.find()) {
|
||||
return matcher.group(1);
|
||||
}
|
||||
|
||||
return null;
|
||||
} catch (Exception e) {
|
||||
log.error("二维码不正确");
|
||||
throw new InnerException("扫码核销失败,二维码不正确");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 抖音验券准备返回抖音验券对象
|
||||
*/
|
||||
@Override
|
||||
public CertificatePrepareResponse prepare(CertificatePrepareRequest req) {
|
||||
// 获取当前有效的access_token
|
||||
String accessToken = douyinTokenManager.getCurrentToken();
|
||||
|
||||
if (accessToken == null || accessToken.isEmpty()) {
|
||||
throw new RuntimeException("无法获取有效的access_token");
|
||||
}
|
||||
|
||||
//抖音验券请求
|
||||
try {
|
||||
Config config = new Config().setClientKey(CLIENT_KEY).setClientSecret(CLIENT_SECRET);
|
||||
Client client = new Client(config);
|
||||
|
||||
CertificatePrepareRequest sdkRequest = new CertificatePrepareRequest();
|
||||
sdkRequest.setAccessToken(accessToken);
|
||||
sdkRequest.setAccountId(ACCOUNT_ID);
|
||||
|
||||
String encryptedData = resolveShortUrlToGetObjectId(req.getEncryptedData());
|
||||
sdkRequest.setEncryptedData(encryptedData);
|
||||
|
||||
sdkRequest.setPoiId(req.getPoiId());
|
||||
CertificatePrepareResponse sdkResponse = client.CertificatePrepare(sdkRequest);
|
||||
System.out.println(JSONObject.toJSONString(sdkResponse));
|
||||
|
||||
if (sdkResponse.getExtra().getErrorCode() != 0){
|
||||
throw new RuntimeException("券验证失败:" + sdkResponse.getExtra().getDescription());
|
||||
}
|
||||
|
||||
return sdkResponse;
|
||||
|
||||
} catch (TeaException e) {
|
||||
throw new RuntimeException("券验证失败");
|
||||
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("券验证失败");
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CertificateVerifyResponse verify(CertificateVerifyRequest req) {
|
||||
// 获取当前有效的access_token
|
||||
String accessToken = douyinTokenManager.getCurrentToken();
|
||||
|
||||
if (accessToken == null || accessToken.isEmpty()) {
|
||||
throw new RuntimeException("无法获取有效的access_token");
|
||||
}
|
||||
|
||||
try{
|
||||
Config config = new Config().setClientKey(CLIENT_KEY).setClientSecret(CLIENT_SECRET);
|
||||
Client client = new Client(config);
|
||||
|
||||
CertificateVerifyRequest sdkRequest = new CertificateVerifyRequest();
|
||||
sdkRequest.setAccessToken(accessToken);
|
||||
sdkRequest.setAccountId(ACCOUNT_ID);
|
||||
sdkRequest.setPoiId(req.getPoiId());
|
||||
sdkRequest.setVerifyToken(req.getVerifyToken());
|
||||
|
||||
CertificateVerifyResponse sdkResponse = client.CertificateVerify(sdkRequest);
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CertificateCancelResponse cancel(CertificateCancelRequest req) {
|
||||
// 获取当前有效的access_token
|
||||
String accessToken = douyinTokenManager.getCurrentToken();
|
||||
|
||||
if (accessToken == null || accessToken.isEmpty()) {
|
||||
throw new RuntimeException("无法获取有效的access_token");
|
||||
}
|
||||
|
||||
try{
|
||||
|
||||
Config config = new Config().setClientKey(CLIENT_KEY).setClientSecret(CLIENT_SECRET);
|
||||
Client client = new Client(config);
|
||||
|
||||
CertificateCancelRequest sdkRequest = new CertificateCancelRequest();
|
||||
sdkRequest.setAccessToken(accessToken);
|
||||
sdkRequest.setVerifyId(req.getVerifyId());
|
||||
sdkRequest.setCertificateId(req.getCertificateId());
|
||||
|
||||
CertificateCancelResponse sdkResponse = client.CertificateCancel(sdkRequest);
|
||||
System.out.println(JSONObject.toJSONString(sdkResponse));
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,49 @@
|
||||
package com.sczx.order.service.impl;
|
||||
|
||||
import com.sczx.order.common.enums.CouponTypeEnum;
|
||||
import com.sczx.order.dto.GroupBuyOrderInfoDto;
|
||||
import com.sczx.order.dto.SimpleUserInfoDTO;
|
||||
import com.sczx.order.exception.BizException;
|
||||
import com.sczx.order.service.GroupBuyCouponService;
|
||||
import com.sczx.order.service.MeiTuanService;
|
||||
import com.sczx.order.thirdpart.integration.UserInteg;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* @Author: 张黎
|
||||
* @Date: 2025/10/27/20:48
|
||||
* @Description:
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class GroupBuyCouponServiceImpl implements GroupBuyCouponService {
|
||||
|
||||
|
||||
@Autowired
|
||||
private UserInteg userInteg;
|
||||
|
||||
@Autowired
|
||||
private MeiTuanService meiTuanService;
|
||||
|
||||
@Override
|
||||
public GroupBuyOrderInfoDto getGroupBuyOrderInfoDto(String couponCode, String couponType, String mobile) {
|
||||
SimpleUserInfoDTO userInfoDTO = userInteg.getUInfoByMobile(mobile);
|
||||
if(userInfoDTO==null){
|
||||
throw new BizException("用户不存在");
|
||||
}
|
||||
if(userInfoDTO.getAuthed()==0){
|
||||
throw new BizException("用户未实名认证");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkCouponCode(String couponCode, String couponType) {
|
||||
if(CouponTypeEnum.MT.getCode().equals(couponType)){
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,133 @@
|
||||
package com.sczx.order.service.impl;
|
||||
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.meituan.sdk.DefaultMeituanClient;
|
||||
import com.meituan.sdk.MeituanClient;
|
||||
import com.meituan.sdk.MeituanResponse;
|
||||
import com.meituan.sdk.auth.MeituanTokenResponse;
|
||||
import com.meituan.sdk.internal.exceptions.MtSdkException;
|
||||
import com.meituan.sdk.model.ddzh.tuangou.tuangouReceiptConsume.TuangouReceiptConsumeRequest;
|
||||
import com.meituan.sdk.model.ddzh.tuangou.tuangouReceiptConsume.TuangouReceiptConsumeResponse;
|
||||
import com.meituan.sdk.model.ddzh.tuangou.tuangouReceiptPrepare.TuangouReceiptPrepareRequest;
|
||||
import com.meituan.sdk.model.ddzh.tuangou.tuangouReceiptPrepare.TuangouReceiptPrepareResponse;
|
||||
import com.sczx.order.exception.BizException;
|
||||
import com.sczx.order.service.MeiTuanService;
|
||||
import com.sczx.order.thirdpart.integration.StoreInteg;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
public class MeiTuanServiceImpl implements MeiTuanService {
|
||||
|
||||
|
||||
private Long DeveloperId = 116997L;
|
||||
|
||||
private String Signkey = "n8xlhtshk7t1luvi";
|
||||
|
||||
//private String accessToken = "V2-26b8d231854d3fdf6a5c06273377a65e441e4c9f1c8cea4959c510bf0dd19ed7657e34bebe4b74aa455b80d3c757cd8a66e3ece9148e6d6838778db5f9600cf383dbf89c0cc27f07f777c98649bd94fe";
|
||||
|
||||
private String accessToken = "V2-549da132ffebe5ce5731a17ae166cb899e13c579900d6cbc4163b60e4d40440ccbe8e56d25c3341cd1003c5529c407085c06af2eb41d2d091353b4d2be6f887582d9d4bf247cf9a511581ad46ade47e8";
|
||||
|
||||
@Autowired
|
||||
private StoreInteg storeInteg;
|
||||
|
||||
@Override
|
||||
public MeituanTokenResponse getAccessToken(String code, String state) {
|
||||
try {
|
||||
// 使用美团SDK构建客户端
|
||||
MeituanClient client = DefaultMeituanClient.builder(DeveloperId, Signkey).build();
|
||||
|
||||
|
||||
// 使用美团SDK的getOAuthToken方法获取token
|
||||
MeituanTokenResponse response = client.getOAuthToken(58, code);
|
||||
|
||||
|
||||
log.info("获取access_token响应结果: {}", JSONObject.toJSONString(response));
|
||||
String token = response.getData().getAccessToken();
|
||||
|
||||
storeInteg.recordToken(state, token);
|
||||
|
||||
return null;
|
||||
|
||||
|
||||
} catch (Exception e) {
|
||||
throw new BizException("获取access_token失败");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public MeituanTokenResponse prepare(String code) {
|
||||
try {
|
||||
MeituanClient meituanClient = DefaultMeituanClient.builder(DeveloperId, Signkey).build();
|
||||
|
||||
TuangouReceiptPrepareRequest tuangouReceiptPrepareRequest = new TuangouReceiptPrepareRequest();
|
||||
|
||||
tuangouReceiptPrepareRequest.setReceiptCode("0106972239359");
|
||||
|
||||
String appAuthToken = accessToken;
|
||||
MeituanResponse<TuangouReceiptPrepareResponse> response = meituanClient.invokeApi(tuangouReceiptPrepareRequest, appAuthToken);
|
||||
|
||||
log.info("获取access_token响应结果: {}", JSONObject.toJSONString(response));
|
||||
|
||||
if (response.isSuccess()) {
|
||||
TuangouReceiptPrepareResponse resp = response.getData();
|
||||
System.out.println(resp);
|
||||
} else {
|
||||
System.out.println("调用失败");
|
||||
}
|
||||
return null;
|
||||
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("获取access_token异常", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public MeituanTokenResponse refreshAccessToken(String refreshToken) {
|
||||
try {
|
||||
MeituanClient meituanClient = DefaultMeituanClient.builder(DeveloperId, Signkey).build();
|
||||
|
||||
MeituanTokenResponse response = meituanClient.refreshToken(58, refreshToken);
|
||||
|
||||
return response;
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("获取access_token异常", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public MeituanResponse<TuangouReceiptConsumeResponse> consume (String code) {
|
||||
try {
|
||||
MeituanClient meituanClient = DefaultMeituanClient.builder(DeveloperId, Signkey).build();
|
||||
|
||||
TuangouReceiptConsumeRequest tuangouReceiptConsumeRequest = new TuangouReceiptConsumeRequest();
|
||||
|
||||
tuangouReceiptConsumeRequest.setReceiptCode("0106972239359");
|
||||
tuangouReceiptConsumeRequest.setCount(1);
|
||||
tuangouReceiptConsumeRequest.setRequestId("fdae143414");
|
||||
tuangouReceiptConsumeRequest.setAppShopAccountName("customer");
|
||||
tuangouReceiptConsumeRequest.setAppShopAccount("customer");
|
||||
|
||||
|
||||
String appAuthToken = accessToken;
|
||||
MeituanResponse<TuangouReceiptConsumeResponse> response = meituanClient.invokeApi(tuangouReceiptConsumeRequest, appAuthToken);
|
||||
|
||||
log.info("获取access_token响应结果: {}", JSONObject.toJSONString(response));
|
||||
return response;
|
||||
} catch (MtSdkException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -5,16 +5,18 @@ import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.sczx.order.common.enums.DistribTypeEnum;
|
||||
import com.sczx.order.common.enums.WalletChangeTypeEnum;
|
||||
import com.sczx.order.dto.OrderDistribDTO;
|
||||
import com.sczx.order.dto.OrderDistribQueryReq;
|
||||
import com.sczx.order.exception.BizException;
|
||||
import com.sczx.order.po.*;
|
||||
import com.sczx.order.po.BaseUserReferralPO;
|
||||
import com.sczx.order.po.OrderDistribPO;
|
||||
import com.sczx.order.po.OrderMainPO;
|
||||
import com.sczx.order.repository.*;
|
||||
import com.sczx.order.service.OrderDistribService;
|
||||
import com.sczx.order.thirdpart.dto.CompanyDTO;
|
||||
import com.sczx.order.thirdpart.dto.CompanyStoreDTO;
|
||||
import com.sczx.order.thirdpart.dto.SysConfigDTO;
|
||||
import com.sczx.order.thirdpart.dto.req.DistibIncomeReq;
|
||||
import com.sczx.order.thirdpart.integration.StoreInteg;
|
||||
import com.sczx.order.thirdpart.integration.UserInteg;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@ -24,7 +26,6 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
@ -115,30 +116,39 @@ public class OrderDistribServiceImpl implements OrderDistribService {
|
||||
.set(OrderMainPO::getDistribed, 1);
|
||||
orderMainRepo.update(updateMainWrapper);
|
||||
|
||||
//更新推荐信息,防止重复分润
|
||||
LambdaUpdateWrapper<BaseUserReferralPO> updateWrapper = new LambdaUpdateWrapper<>();
|
||||
updateWrapper.eq(BaseUserReferralPO::getUserId, orderMainPO.getCustomerId())
|
||||
.set(BaseUserReferralPO::getReferralOrderNo, storeDistribPO.getOrderNo());
|
||||
baseUserReferralRepo.update(updateWrapper);
|
||||
|
||||
//门店钱包入账
|
||||
LambdaQueryWrapper<BaseWalletPO> queryWalletWrapper = new LambdaQueryWrapper<>();
|
||||
queryWalletWrapper.eq(BaseWalletPO::getUserId, orderMainPO.getOperatorId()).last(" limit 1");
|
||||
BaseWalletPO baseWalletPO = baseWalletRepo.getOne(queryWalletWrapper);
|
||||
if(baseWalletPO != null){
|
||||
LambdaUpdateWrapper<BaseWalletPO> updateWalletWrapper = new LambdaUpdateWrapper<>();
|
||||
updateWalletWrapper.eq(BaseWalletPO::getUserId, orderMainPO.getOperatorId())
|
||||
.set(BaseWalletPO::getBalance, baseWalletPO.getBalance().add(storeDistribPO.getDistribAmount()));
|
||||
baseWalletRepo.update(updateWalletWrapper);
|
||||
DistibIncomeReq distibIncomeReq = new DistibIncomeReq();
|
||||
distibIncomeReq.setStoreId(orderMainPO.getStoreId());
|
||||
distibIncomeReq.setAmount(storeDistribPO.getDistribAmount());
|
||||
storeInteg.distibIncome(distibIncomeReq);
|
||||
|
||||
BaseWalletChangePO baseWalletChangePO = new BaseWalletChangePO();
|
||||
baseWalletChangePO.setUserId(orderMainPO.getOperatorId());
|
||||
baseWalletChangePO.setChangeType(WalletChangeTypeEnum.REFERRAL.getCode());
|
||||
baseWalletChangePO.setChangeTime(LocalDateTime.now());
|
||||
baseWalletChangePO.setChangeAmount(storeDistribPO.getDistribAmount());
|
||||
baseWalletChangePO.setReferralOrderNo(orderMainPO.getOrderNo());
|
||||
baseWalletChangeRepo.save(baseWalletChangePO);
|
||||
// LambdaQueryWrapper<BaseWalletPO> queryWalletWrapper = new LambdaQueryWrapper<>();
|
||||
// queryWalletWrapper.eq(BaseWalletPO::getUserId, orderMainPO.getStoreId()).last(" limit 1");
|
||||
// BaseWalletPO baseWalletPO = baseWalletRepo.getOne(queryWalletWrapper);
|
||||
// if(baseWalletPO != null){
|
||||
// LambdaUpdateWrapper<BaseWalletPO> updateWalletWrapper = new LambdaUpdateWrapper<>();
|
||||
// updateWalletWrapper.eq(BaseWalletPO::getUserId, orderMainPO.getOperatorId())
|
||||
// .set(BaseWalletPO::getBalance, baseWalletPO.getBalance().add(storeDistribPO.getDistribAmount()));
|
||||
// baseWalletRepo.update(updateWalletWrapper);
|
||||
// }else {
|
||||
// baseWalletPO = new BaseWalletPO();
|
||||
// baseWalletPO.setUserId(Long.valueOf(companyStoreDTO.getId()));
|
||||
// baseWalletPO.setUserName(companyStoreDTO.getName());
|
||||
// }
|
||||
// BaseWalletChangePO baseWalletChangePO = new BaseWalletChangePO();
|
||||
// baseWalletChangePO.setUserId(orderMainPO.getOperatorId());
|
||||
// baseWalletChangePO.setChangeType(WalletChangeTypeEnum.REFERRAL.getCode());
|
||||
// baseWalletChangePO.setChangeTime(LocalDateTime.now());
|
||||
// baseWalletChangePO.setChangeAmount(storeDistribPO.getDistribAmount());
|
||||
// baseWalletChangePO.setReferralOrderNo(orderMainPO.getOrderNo());
|
||||
// baseWalletChangeRepo.save(baseWalletChangePO);
|
||||
|
||||
//更新推荐信息,防止重复分润
|
||||
LambdaUpdateWrapper<BaseUserReferralPO> updateWrapper = new LambdaUpdateWrapper<>();
|
||||
updateWrapper.eq(BaseUserReferralPO::getUserId, orderMainPO.getCustomerId())
|
||||
.set(BaseUserReferralPO::getReferralOrderNo, storeDistribPO.getOrderNo());
|
||||
baseUserReferralRepo.update(updateWrapper);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@ -3,6 +3,10 @@ package com.sczx.order.service.impl;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.douyin.openapi.client.models.CertificatePrepareRequest;
|
||||
import com.douyin.openapi.client.models.CertificatePrepareResponse;
|
||||
import com.douyin.openapi.client.models.CertificateVerifyRequest;
|
||||
import com.douyin.openapi.client.models.CertificateVerifyResponse;
|
||||
import com.sczx.order.common.constant.RedisKeyConstants;
|
||||
import com.sczx.order.common.enums.*;
|
||||
import com.sczx.order.convert.OrderCarImgConvert;
|
||||
@ -13,15 +17,10 @@ import com.sczx.order.exception.BizException;
|
||||
import com.sczx.order.exception.InnerException;
|
||||
import com.sczx.order.po.*;
|
||||
import com.sczx.order.repository.*;
|
||||
import com.sczx.order.service.OrderDistribService;
|
||||
import com.sczx.order.service.OrderService;
|
||||
import com.sczx.order.service.PayService;
|
||||
import com.sczx.order.service.*;
|
||||
import com.sczx.order.thirdpart.dto.*;
|
||||
import com.sczx.order.thirdpart.dto.req.*;
|
||||
import com.sczx.order.thirdpart.integration.CarInteg;
|
||||
import com.sczx.order.thirdpart.integration.PayInteg;
|
||||
import com.sczx.order.thirdpart.integration.StoreInteg;
|
||||
import com.sczx.order.thirdpart.integration.SyncInteg;
|
||||
import com.sczx.order.thirdpart.integration.*;
|
||||
import com.sczx.order.utils.JwtUtil;
|
||||
import com.sczx.order.utils.OrderUtil;
|
||||
import com.sczx.order.utils.RedisUtil;
|
||||
@ -36,6 +35,7 @@ import org.springframework.util.CollectionUtils;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Slf4j
|
||||
@ -60,6 +60,9 @@ public class OrderServiceImpl implements OrderService {
|
||||
@Autowired
|
||||
private OrderCarChangeRepo orderCarChangeRepo;
|
||||
|
||||
@Autowired
|
||||
private ElectronicFenceRuleRepo electronicFenceRuleRepo;
|
||||
|
||||
@Autowired
|
||||
private JwtUtil jwtUtil;
|
||||
|
||||
@ -81,6 +84,15 @@ public class OrderServiceImpl implements OrderService {
|
||||
@Autowired
|
||||
private SyncInteg syncInteg;
|
||||
|
||||
@Autowired
|
||||
private GroupBuyCouponService groupBuyCouponService;
|
||||
|
||||
@Autowired
|
||||
private DouyinService douyinService;
|
||||
|
||||
@Autowired
|
||||
private MeiTuanService meiTuanService;
|
||||
|
||||
@Override
|
||||
public OrderMainPO queryOrderMainPoByOrderNo(String orderNo, String delFlag) {
|
||||
LambdaQueryWrapper<OrderMainPO> currentOrderWrapper = new LambdaQueryWrapper<>();
|
||||
@ -89,6 +101,72 @@ public class OrderServiceImpl implements OrderService {
|
||||
return orderMainRepo.getOne(currentOrderWrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public OrderDetailDTO verifyGroupBuyCoupons(VerifyGroupBuyCouponsReq req){
|
||||
|
||||
|
||||
if (req.getCouponType() == CouponTypeEnum.MT.getCode()){
|
||||
//TODO 调用美团验券接口
|
||||
|
||||
}else if (req.getCouponType() == CouponTypeEnum.DY.getCode()){
|
||||
|
||||
//根据门店ID获取抖音门店ID
|
||||
CompanyStoreDTO store = storeInteg.getStoreById(req.getStoreId().intValue());
|
||||
String poiId = store.getDyStoreId();
|
||||
|
||||
//调用抖音验券接口
|
||||
CertificatePrepareRequest prepareRequest = new CertificatePrepareRequest();
|
||||
|
||||
prepareRequest.setPoiId(poiId);
|
||||
prepareRequest.setEncryptedData(req.getCouponCode());
|
||||
|
||||
CertificatePrepareResponse response =douyinService.prepare(prepareRequest);
|
||||
//获取核销所需信息
|
||||
String verifyToken = response.getData().getVerifyToken();
|
||||
AtomicReference<String> phone = new AtomicReference<>("");
|
||||
response.getData().getCertificates().forEach(certificate -> {
|
||||
Long certificateId = certificate.getCertificateId();
|
||||
String skuId = certificate.getSku().getSkuId();
|
||||
certificate.getReserveInfo().getOrderReserveUserInfoList().forEach(orderReserveUserInfo -> {
|
||||
phone.set(orderReserveUserInfo.getPhone());
|
||||
System.out.println(orderReserveUserInfo.getPhone());
|
||||
});
|
||||
});
|
||||
|
||||
String finalPhone = phone.get();
|
||||
|
||||
//校验用户是否存在,是否实名认证
|
||||
GroupBuyOrderInfoDto groupBuyOrderInfoDTO = groupBuyCouponService.getGroupBuyOrderInfoDto(req.getCouponCode(), req.getCouponType(), req.getMobile());
|
||||
|
||||
if (finalPhone != null && !finalPhone.isEmpty()) {
|
||||
// 如果校验券没有返回手机号码,则使用前端所传手机号码
|
||||
log.info("您所团购的订单未填写手机号,将使用您提交给门店的手机号生成租车订单");
|
||||
|
||||
}else{
|
||||
// 如果校验券有返回手机号码,则使用前端所传手机号码与该脱敏手机号码比对
|
||||
}
|
||||
|
||||
//核销抖音团购券
|
||||
CertificateVerifyRequest verifyRequest = new CertificateVerifyRequest();
|
||||
verifyRequest.setVerifyToken(verifyToken);
|
||||
verifyRequest.setPoiId(poiId);
|
||||
|
||||
CertificateVerifyResponse verifyResponse =douyinService.verify(verifyRequest);
|
||||
|
||||
verifyResponse.getData().getVerifyResults().forEach(verifyResult -> {
|
||||
//撤销验券需要下面两个值
|
||||
verifyResult.getCertificateId();
|
||||
verifyResult.getVerifyId();
|
||||
});
|
||||
|
||||
//TODO 生成订单
|
||||
|
||||
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Override
|
||||
public RentCarOrderResultDTO submitRentCarOrder(RentCarOrderReq rentCarOrderReq) {
|
||||
@ -182,6 +260,7 @@ public class OrderServiceImpl implements OrderService {
|
||||
depositOrder.setAmount(rentBatteyRuleDTO.getRentPrice());
|
||||
depositOrder.setCreatedAt(LocalDateTime.now());
|
||||
depositOrder.setPaymentMethod(paymentType);
|
||||
depositOrder.setReturnTime(endRentTime);
|
||||
orderSubPOList.add(depositOrder);
|
||||
}
|
||||
//生成租车订单
|
||||
@ -239,6 +318,7 @@ public class OrderServiceImpl implements OrderService {
|
||||
}
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Override
|
||||
public RentCarOrderResultDTO depositFreeSubmitRentCarOrder(RentCarOrderReq rentCarOrderReq) {
|
||||
log.info("开始发起免押 : {}", rentCarOrderReq);
|
||||
@ -307,10 +387,11 @@ public class OrderServiceImpl implements OrderService {
|
||||
String paymentType = PaymentTypeEnum.ZFB_PAY.getCode();
|
||||
List<OrderSubPO> orderSubPOList = new ArrayList<>();
|
||||
|
||||
|
||||
//生成免押订单
|
||||
OrderSubPO noDepositOrder = new OrderSubPO();
|
||||
noDepositOrder.setSuborderNo(OrderUtil.generateSubOrderNo(OrderUtil.MY_PREFIX));
|
||||
noDepositOrder.setPaymentId(OrderUtil.generateSubOrderNo(OrderUtil.FZ_PREFIX));
|
||||
noDepositOrder.setPaymentId(OrderUtil.generateSubOrderNo(OrderUtil.ZF_PREFIX));
|
||||
noDepositOrder.setSuborderType(SubOrderTypeEnum.NO_DEPOSIT.getCode());
|
||||
noDepositOrder.setAmount(orderMainPO.getDepositPrice());
|
||||
noDepositOrder.setCreatedAt(LocalDateTime.now());
|
||||
@ -319,6 +400,7 @@ public class OrderServiceImpl implements OrderService {
|
||||
orderSubPOList.add(noDepositOrder);
|
||||
|
||||
String paymentId = OrderUtil.generateSubOrderNo(OrderUtil.ZF_PREFIX);
|
||||
|
||||
//如果选择了租电套餐,则还需要生成租电子订单
|
||||
if(rentBatteyRuleDTO!=null){
|
||||
rentBatteyRuleDTO = carInteg.getRentBatteyRuleByBatteyRuleId(rentCarOrderReq.getRentBatteyRuleId());
|
||||
@ -330,6 +412,7 @@ public class OrderServiceImpl implements OrderService {
|
||||
rentBatteyRuleOrder.setPaymentMethod(paymentType);
|
||||
rentBatteyRuleOrder.setPayStatus(PayStatusEnum.INIT.getCode());
|
||||
rentBatteyRuleOrder.setPaymentId(paymentId);
|
||||
rentBatteyRuleOrder.setReturnTime(endRentTime);
|
||||
orderSubPOList.add(rentBatteyRuleOrder);
|
||||
}
|
||||
//生成租车订单
|
||||
@ -384,6 +467,7 @@ public class OrderServiceImpl implements OrderService {
|
||||
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Override
|
||||
public RentCarOrderResultDTO depositFreePayRentCarOrder(RentCarOrderReq rentCarOrderReq) {
|
||||
SimpleUserInfoDTO userInfoDTO = jwtUtil.getUserInfoFromToken();
|
||||
@ -421,6 +505,10 @@ public class OrderServiceImpl implements OrderService {
|
||||
//开始发起支付
|
||||
UnifiedPaymentInfoDTO unifiedPaymentInfoDTO = payService.prepayOrder(rentCarOrder.getPaymentMethod(),orderMainPO.getRentCarRuleId().toString(),orderMainPO.getOperatorId(),rentCarOrder.getPaymentId(),userInfoDTO
|
||||
,orderMainPO.getOrderAmount());
|
||||
|
||||
//免押代扣支付-过审验证用
|
||||
// UnifiedPaymentInfoDTO unifiedPaymentInfoDTO = payService.zhimaPayOrder("闪充智行租车免押支付",orderMainPO.getOperatorId(),rentCarOrder.getPaymentId()
|
||||
// ,noDepositOrder.getTransactionId(),userInfoDTO.getAlipayOpenid(),orderMainPO.getOrderAmount());
|
||||
LambdaUpdateWrapper<OrderSubPO> updateWrapper = new LambdaUpdateWrapper<>();
|
||||
updateWrapper.eq(OrderSubPO::getSuborderId, noDepositOrder.getSuborderId())
|
||||
.eq(OrderSubPO::getDelFlag, "0")
|
||||
@ -449,6 +537,161 @@ public class OrderServiceImpl implements OrderService {
|
||||
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Override
|
||||
public RentCarOrderResultDTO thirdPlatformRentCarOrder(RentCarThirdPlatformOrderReq rentCarOrderReq) {
|
||||
|
||||
LambdaQueryWrapper<OrderMainPO> currentOrderWrapper = new LambdaQueryWrapper<>();
|
||||
currentOrderWrapper.eq(OrderMainPO::getCustomerId, rentCarOrderReq.getCustomerId())
|
||||
.notIn(OrderMainPO::getOrderStatus, Arrays.asList(OrderStatusEnum.AUTO_END.getCode(), OrderStatusEnum.MANUAL_END.getCode()))
|
||||
.eq(OrderMainPO::getDelFlag, "0");
|
||||
List<OrderMainPO> currentOrderList = orderMainRepo.list(currentOrderWrapper);
|
||||
OrderMainPO waitPayOrder = currentOrderList.stream().filter(order -> order.getOrderStatus().equals(OrderStatusEnum.WAIT_PAY.getCode())).findFirst().orElse(null);
|
||||
if(!currentOrderList.isEmpty() && waitPayOrder==null){
|
||||
throw new BizException("您有未完成的订单,请先完成订单");
|
||||
}
|
||||
if(waitPayOrder!=null){
|
||||
log.info("存在待支付的订单,取消订单");
|
||||
PayOrderReq payOrderReq = new PayOrderReq();
|
||||
payOrderReq.setOrderNo(waitPayOrder.getOrderNo());
|
||||
cancelOrder(payOrderReq,null);
|
||||
}
|
||||
|
||||
//判断是否存有空闲车辆可用
|
||||
LambdaQueryWrapper<CarPO> carWrapper = new LambdaQueryWrapper<>();
|
||||
carWrapper.eq(CarPO::getModelId, rentCarOrderReq.getCarModelId())
|
||||
.eq(CarPO::getDelFlag, "0")
|
||||
.eq(CarPO::getBrsStatus, "0")
|
||||
.eq(CarPO::getStoreId, rentCarOrderReq.getStoreId());
|
||||
List<CarPO> carPOList = carRepo.list(carWrapper);
|
||||
if(CollectionUtils.isEmpty(carPOList)){
|
||||
throw new BizException("门店没有该车型的车辆可租");
|
||||
}
|
||||
|
||||
//获取门店信息
|
||||
// CompanyStoreDTO companyStoreDTO = storeInteg.getStoreById(Integer.valueOf(rentCarOrderReq.getStoreId().toString()));
|
||||
// if(Objects.isNull(companyStoreDTO)){
|
||||
// throw new BizException("运营商或门店已下架");
|
||||
// }
|
||||
|
||||
|
||||
CarModelSimpleDTO carModelSimpleDTO = carInteg.getCarModelByModelId(rentCarOrderReq.getCarModelId());
|
||||
|
||||
RentCarRuleDTO rentCarRuleDTO = carInteg.getRentCarRuleByCarRuleId(rentCarOrderReq.getRentCarRuleId());
|
||||
|
||||
RentBatteyRuleDTO rentBatteyRuleDTO = null;
|
||||
if(rentCarOrderReq.getRentBatteyRuleId()!=null){
|
||||
rentBatteyRuleDTO = carInteg.getRentBatteyRuleByBatteyRuleId(rentCarOrderReq.getRentBatteyRuleId());
|
||||
}
|
||||
|
||||
String redisLockKey = RedisKeyConstants.ORDER_SUB_KEY + rentCarOrderReq.getCustomerId();
|
||||
|
||||
|
||||
SimpleUserInfoDTO userInfoDTO = new SimpleUserInfoDTO();
|
||||
userInfoDTO.setUserId(Math.toIntExact(rentCarOrderReq.getCustomerId()));
|
||||
userInfoDTO.setUserName(rentCarOrderReq.getCustomerName());
|
||||
userInfoDTO.setPhoneNumber(rentCarOrderReq.getCustomerPhone());
|
||||
|
||||
if(redisUtil.getRedisLock(redisLockKey, "租车下单")) {
|
||||
try{
|
||||
|
||||
//TODO 这里保存订单要做事物处理
|
||||
//生成订单主表
|
||||
OrderMainPO orderMainPO = OrderConvert.INSTANCE.subOrderToPo(rentCarOrderReq, userInfoDTO, rentCarRuleDTO);
|
||||
//orderMainPO.setOperatorId(Long.valueOf(companyStoreDTO.getOperatingCompanyId()));
|
||||
orderMainPO.setOrderNo(OrderUtil.generateOrderNo());
|
||||
orderMainPO.setOrderStatus(OrderStatusEnum.WAIT_PICK.getCode());
|
||||
orderMainPO.setFirstOrderTime(LocalDateTime.now());
|
||||
|
||||
//设置预计还车时间
|
||||
LocalDateTime endRentTime = OrderUtil.getEndRentTime(orderMainPO.getFirstOrderTime(),1,rentCarRuleDTO.getRentalDays(), rentCarRuleDTO.getRentalType());
|
||||
orderMainPO.setEndRentTime(endRentTime);
|
||||
|
||||
|
||||
//生成子表订单
|
||||
String paymentType = rentCarOrderReq.getOrderSource();
|
||||
|
||||
List<OrderSubPO> orderSubPOList = new ArrayList<>();
|
||||
|
||||
//如果未开通免押则要生成押金订单
|
||||
if(!rentCarOrderReq.getIsDepositFree()){
|
||||
OrderSubPO depositOrder = new OrderSubPO();
|
||||
depositOrder.setSuborderNo(OrderUtil.generateSubOrderNo(OrderUtil.YJ_PREFIX));
|
||||
depositOrder.setSuborderType(SubOrderTypeEnum.DEPOSIT.getCode());
|
||||
depositOrder.setAmount(orderMainPO.getDepositPrice());
|
||||
depositOrder.setCreatedAt(LocalDateTime.now());
|
||||
depositOrder.setPaymentMethod(paymentType);
|
||||
depositOrder.setTransactionId(rentCarOrderReq.getThirdOrderNo());
|
||||
orderSubPOList.add(depositOrder);
|
||||
}
|
||||
//如果选择了租电套餐,则还需要生成租电子订单
|
||||
if(rentBatteyRuleDTO!=null){
|
||||
rentBatteyRuleDTO = carInteg.getRentBatteyRuleByBatteyRuleId(rentCarOrderReq.getRentBatteyRuleId());
|
||||
OrderSubPO depositOrder = new OrderSubPO();
|
||||
depositOrder.setSuborderNo(OrderUtil.generateSubOrderNo(OrderUtil.ZD_PREFIX));
|
||||
depositOrder.setSuborderType(SubOrderTypeEnum.RENTBATTEY.getCode());
|
||||
depositOrder.setAmount(rentBatteyRuleDTO.getRentPrice());
|
||||
depositOrder.setCreatedAt(LocalDateTime.now());
|
||||
depositOrder.setPaymentMethod(paymentType);
|
||||
depositOrder.setReturnTime(endRentTime);
|
||||
depositOrder.setTransactionId(rentCarOrderReq.getThirdOrderNo());
|
||||
orderSubPOList.add(depositOrder);
|
||||
}
|
||||
//生成租车订单
|
||||
BigDecimal rentCarOrderAmount = OrderUtil.getRentCarAmount(rentCarRuleDTO.getRentalType(), rentCarRuleDTO.getRentalPrice(), rentCarRuleDTO.getRentalDays());
|
||||
OrderSubPO rentOrder = new OrderSubPO();
|
||||
rentOrder.setSuborderNo(OrderUtil.generateSubOrderNo(OrderUtil.ZC_PREFIX));
|
||||
rentOrder.setSuborderType(SubOrderTypeEnum.RENTCAR.getCode());
|
||||
rentOrder.setAmount(rentCarOrderAmount);
|
||||
rentOrder.setCreatedAt(LocalDateTime.now());
|
||||
rentOrder.setPaymentMethod(paymentType);
|
||||
rentOrder.setReturnTime(endRentTime);
|
||||
rentOrder.setTransactionId(rentCarOrderReq.getThirdOrderNo());
|
||||
orderSubPOList.add(rentOrder);
|
||||
|
||||
BigDecimal orderAmount = orderSubPOList.stream().map(OrderSubPO::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||
orderMainPO.setOrderAmount(orderAmount);
|
||||
|
||||
//发起支付返回预支付信息
|
||||
String paymentId = OrderUtil.generateSubOrderNo(OrderUtil.ZF_PREFIX);
|
||||
|
||||
|
||||
for(OrderSubPO orderSubPO : orderSubPOList){
|
||||
orderSubPO.setPaymentId(paymentId);
|
||||
orderSubPO.setPayStatus(PayStatusEnum.USERPAYING.getCode());
|
||||
}
|
||||
|
||||
orderMainRepo.save(orderMainPO);
|
||||
|
||||
orderSubPOList.forEach(orderSubPO -> {
|
||||
orderSubPO.setOrderId(orderMainPO.getOrderId());
|
||||
});
|
||||
orderSubRepo.saveBatch(orderSubPOList);
|
||||
|
||||
|
||||
//返回订单信息
|
||||
OrderDTO orderDTO = OrderConvert.INSTANCE.poToDto(orderMainPO);
|
||||
//orderDTO.setCompanyStoreDTO(companyStoreDTO);
|
||||
orderDTO.setCarModelSimpleDTO(carModelSimpleDTO);
|
||||
|
||||
RentCarOrderResultDTO rentCarOrderResultDTO = new RentCarOrderResultDTO();
|
||||
rentCarOrderResultDTO.setOrderMainInfo(orderDTO);
|
||||
//rentCarOrderResultDTO.setUnifiedPaymentInfo(unifiedPaymentInfoDTO);
|
||||
|
||||
return rentCarOrderResultDTO;
|
||||
|
||||
}catch (Exception e){
|
||||
log.warn("下单失败", e);
|
||||
throw e;
|
||||
} finally {
|
||||
redisUtil.deleteRedisLock(redisLockKey);
|
||||
}
|
||||
} else {
|
||||
log.warn("下单失败,锁已被占用");
|
||||
throw new InnerException("服务器正在处理,请稍后再试");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Override
|
||||
@ -521,13 +764,14 @@ public class OrderServiceImpl implements OrderService {
|
||||
//生成租电子订单
|
||||
OrderSubPO rentBatraayOrder = new OrderSubPO();
|
||||
rentBatraayOrder.setOrderId(orderMainPO.getOrderId());
|
||||
rentBatraayOrder.setSuborderNo(OrderUtil.generateSubOrderNo(OrderUtil.ZC_PREFIX));
|
||||
rentBatraayOrder.setSuborderNo(OrderUtil.generateSubOrderNo(OrderUtil.ZD_PREFIX));
|
||||
rentBatraayOrder.setPaymentId(paymentId);
|
||||
rentBatraayOrder.setSuborderType(SubOrderTypeEnum.RENTBATTEY.getCode());
|
||||
rentBatraayOrder.setAmount(rentBatteyOrderAmount);
|
||||
rentBatraayOrder.setCreatedAt(LocalDateTime.now());
|
||||
rentBatraayOrder.setPaymentMethod(paymentType);
|
||||
rentBatraayOrder.setPayStatus(PayStatusEnum.USERPAYING.getCode());
|
||||
rentBatraayOrder.setReturnTime(newEndRentTime);
|
||||
orderSubRepo.save(rentBatraayOrder);
|
||||
}
|
||||
|
||||
@ -593,6 +837,7 @@ public class OrderServiceImpl implements OrderService {
|
||||
,orderAmount);
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Override
|
||||
public void cancelOrder(PayOrderReq payOrderReq,OrderMainPO orderMainPO) {
|
||||
log.info("开始取消订单");
|
||||
@ -606,7 +851,7 @@ public class OrderServiceImpl implements OrderService {
|
||||
|
||||
LambdaQueryWrapper<OrderSubPO> orderSubQueryWrapper = new LambdaQueryWrapper<>();
|
||||
orderSubQueryWrapper.eq(OrderSubPO::getOrderId, orderMainPO.getOrderId());
|
||||
orderSubQueryWrapper.in(OrderSubPO::getPayStatus, Arrays.asList(PayStatusEnum.USERPAYING.getCode(), PayStatusEnum.INIT.getCode()));
|
||||
orderSubQueryWrapper.in(OrderSubPO::getPayStatus, Arrays.asList(PayStatusEnum.USERPAYING.getCode(), PayStatusEnum.INIT.getCode(), PayStatusEnum.SUCCESS.getCode()));
|
||||
orderSubQueryWrapper.orderByDesc(OrderSubPO::getCreatedAt);
|
||||
List<OrderSubPO> orderSubPOList = orderSubRepo.list(orderSubQueryWrapper);
|
||||
boolean closePayOrder = false;
|
||||
@ -634,11 +879,11 @@ public class OrderServiceImpl implements OrderService {
|
||||
//不管取消是否成功,都要删除订单
|
||||
closePayOrder = true;
|
||||
}else {
|
||||
closePayOrder = payService.finishFreezeOrder(Long.valueOf(companyStoreDTO.getOperatingCompanyId()),noDepositOrder.getPaymentId(),noDepositOrder.getTransactionId());
|
||||
closePayOrder = payService.finishFreezeOrder(Long.valueOf(companyStoreDTO.getOperatingCompanyId()),noDepositOrder.getPaymentId(),noDepositOrder.getTransactionId(),noDepositOrder.getAmount());
|
||||
}
|
||||
|
||||
} else if(StringUtils.equalsIgnoreCase(noDepositOrder.getPayStatus(), PayStatusEnum.SUCCESS.getCode())){
|
||||
closePayOrder = payService.finishFreezeOrder(Long.valueOf(companyStoreDTO.getOperatingCompanyId()),noDepositOrder.getPaymentId(),noDepositOrder.getTransactionId());
|
||||
closePayOrder = payService.finishFreezeOrder(Long.valueOf(companyStoreDTO.getOperatingCompanyId()),noDepositOrder.getPaymentId(),noDepositOrder.getTransactionId(),noDepositOrder.getAmount());
|
||||
}
|
||||
if (closePayOrder) {
|
||||
//解冻成功更新状态为解冻成功
|
||||
@ -932,6 +1177,7 @@ public class OrderServiceImpl implements OrderService {
|
||||
orderDetailDTO.setOrderStatus(OrderStatusEnum.RENT_OVERDUE.getCode());
|
||||
LambdaUpdateWrapper<OrderMainPO> updateWrapper = new LambdaUpdateWrapper<>();
|
||||
updateWrapper.set(OrderMainPO::getOrderStatus, OrderStatusEnum.RENT_OVERDUE.getCode());
|
||||
updateWrapper.set(OrderMainPO::getOverdueDays, overdueHours);
|
||||
updateWrapper.eq(OrderMainPO::getOrderId, orderMainPO.getOrderId());
|
||||
orderMainRepo.update(updateWrapper);
|
||||
}
|
||||
@ -971,6 +1217,13 @@ public class OrderServiceImpl implements OrderService {
|
||||
if(StringUtils.equalsIgnoreCase(RentCarTypeEnum.HOUR_RENTAL.getCode(), orderMainPO.getRentalType())){
|
||||
overdueDaysOrHours = OrderUtil.getOrderOverdueHours(orderMainPO.getEndRentTime());
|
||||
}
|
||||
//逾期天数有变化,则更新
|
||||
if(!overdueDaysOrHours.equals(orderMainPO.getOverdueDays())){
|
||||
LambdaUpdateWrapper<OrderMainPO> updateWrapper = new LambdaUpdateWrapper<>();
|
||||
updateWrapper.set(OrderMainPO::getOverdueDays, overdueDaysOrHours);
|
||||
updateWrapper.eq(OrderMainPO::getOrderId, orderMainPO.getOrderId());
|
||||
orderMainRepo.update(updateWrapper);
|
||||
}
|
||||
orderDetailDTO.setOverdueAmount(OrderUtil.getOrderOverdueAmount(overdueDaysOrHours, orderMainPO.getOverdueFee()));
|
||||
//计算续租周期
|
||||
int rerentInterval = OrderUtil.calculateRerentRoundsToCoverOverdue(overdueDaysOrHours, orderMainPO.getRentalDays());
|
||||
@ -1047,7 +1300,6 @@ public class OrderServiceImpl implements OrderService {
|
||||
if(!orderMainPO.getOrderStatus().equals(OrderStatusEnum.WAIT_PICK.getCode()) && !orderMainPO.getOrderStatus().equals(OrderStatusEnum.WAIT_RETURN.getCode())){
|
||||
throw new BizException("订单状态异常,非待取车或待还车状态,无法驳回");
|
||||
}
|
||||
SimpleUserInfoDTO userInfoDTO = jwtUtil.getUserInfoFromToken();
|
||||
|
||||
if(orderMainPO.getOrderStatus().equals(OrderStatusEnum.WAIT_PICK.getCode())){
|
||||
//获取租车子订单
|
||||
@ -1062,6 +1314,7 @@ public class OrderServiceImpl implements OrderService {
|
||||
//变更订单状态,记录结束订单时间,记录订单备注
|
||||
LambdaUpdateWrapper<OrderMainPO> updateWrapper = new LambdaUpdateWrapper<>();
|
||||
updateWrapper.set(OrderMainPO::getOrderStatus, OrderStatusEnum.MANUAL_END.getCode());
|
||||
updateWrapper.set(OrderMainPO::getEndOrderTime, LocalDateTime.now());
|
||||
updateWrapper.set(OrderMainPO::getActEndRentTime, LocalDateTime.now());
|
||||
updateWrapper.eq(OrderMainPO::getOrderNo, rejectOrderReq.getOrderNo());
|
||||
orderMainRepo.update(updateWrapper);
|
||||
@ -1083,6 +1336,32 @@ public class OrderServiceImpl implements OrderService {
|
||||
orderSubRepo.save(fdSubOrder);
|
||||
}
|
||||
}
|
||||
|
||||
LambdaQueryWrapper<OrderSubPO> noDipoSubWrapper = new LambdaQueryWrapper<>();
|
||||
noDipoSubWrapper.eq(OrderSubPO::getOrderId, orderMainPO.getOrderId())
|
||||
.eq(OrderSubPO::getDelFlag, "0")
|
||||
.eq(OrderSubPO::getSuborderType, SubOrderTypeEnum.NO_DEPOSIT.getCode())
|
||||
.eq(OrderSubPO::getPayStatus, PayStatusEnum.SUCCESS).last(" limit 1");
|
||||
OrderSubPO noDepositOrder = orderSubRepo.getOne(noDipoSubWrapper);
|
||||
if(Objects.nonNull(noDepositOrder)){
|
||||
log.info("查询支付宝冻结订单结果");
|
||||
AlipayQueryFreezeRequest alipayQueryFreezeRequest = new AlipayQueryFreezeRequest();
|
||||
alipayQueryFreezeRequest.setOutOrderNo(noDepositOrder.getPaymentId());
|
||||
alipayQueryFreezeRequest.setOperationType("FREEZE");
|
||||
alipayQueryFreezeRequest.setCompanyId(orderMainPO.getOperatorId().toString());
|
||||
AlipayQueryFreezeResponse queryFreezeResponse = payInteg.queryFundFreeze(alipayQueryFreezeRequest);
|
||||
if(queryFreezeResponse!=null){
|
||||
boolean closePayOrder = payService.finishFreezeOrder(orderMainPO.getOperatorId(),noDepositOrder.getPaymentId(),noDepositOrder.getTransactionId(),noDepositOrder.getAmount());
|
||||
if(closePayOrder){
|
||||
//解冻成功更新状态为解冻成功
|
||||
LambdaUpdateWrapper<OrderSubPO> updatenoDepositWrapper = new LambdaUpdateWrapper<>();
|
||||
updatenoDepositWrapper.set(OrderSubPO::getPayStatus, PayStatusEnum.UNFREEZE_SUCCESS.getCode())
|
||||
.eq(OrderSubPO::getSuborderId, noDepositOrder.getSuborderId());
|
||||
orderSubRepo.update(updatenoDepositWrapper);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
LambdaUpdateWrapper<OrderMainPO> updateWrapper = new LambdaUpdateWrapper<>();
|
||||
@ -1123,6 +1402,37 @@ public class OrderServiceImpl implements OrderService {
|
||||
throw new BizException("订单状态异常,非待取车状态");
|
||||
}
|
||||
|
||||
//同步租电订单
|
||||
LambdaQueryWrapper<OrderSubPO> querySubBatteryWrapper = new LambdaQueryWrapper<>();
|
||||
querySubBatteryWrapper.eq(OrderSubPO::getOrderId, orderMainPO.getOrderId())
|
||||
.eq(OrderSubPO::getSuborderType, SubOrderTypeEnum.RENTBATTEY.getCode())
|
||||
.orderByDesc(OrderSubPO::getCreatedAt)
|
||||
.last(" limit 1");
|
||||
OrderSubPO renBatteryOrderSubPO = orderSubRepo.getOne(querySubBatteryWrapper);
|
||||
if(renBatteryOrderSubPO!=null){
|
||||
Map<String, String> result = syncInteg.sendUserMeal(renBatteryOrderSubPO.getSuborderId());
|
||||
String status = result.get("code");
|
||||
if (status.equals("40001") || status.equals("40002") || status.equals("40003") || status.equals("40005") || status.equals("40006")){
|
||||
throw new BizException("此用户在租电APP还有未完成的订单,请联系用户完成租电订单或是驳回此租车订单");
|
||||
}
|
||||
}
|
||||
//绑定电子围栏
|
||||
LambdaQueryWrapper<ElectronicFenceRulePO> electqueryWrapper = new LambdaQueryWrapper<>();
|
||||
electqueryWrapper.eq(ElectronicFenceRulePO::getCarRuleId, orderMainPO.getRentCarRuleId())
|
||||
.eq(ElectronicFenceRulePO::getDelFlag, "0")
|
||||
.orderByAsc(ElectronicFenceRulePO::getSortOrder);
|
||||
ElectronicFenceRulePO electronicFenceRulePO = electronicFenceRuleRepo.getOne(electqueryWrapper);
|
||||
|
||||
if (electronicFenceRulePO != null) {
|
||||
String redisEfenceKey = RedisKeyConstants.E_Fence_KEY + carDTO.getLotNumber();
|
||||
redisUtil.set(redisEfenceKey, electronicFenceRulePO.getElectronicFenceId().toString());
|
||||
log.info("电子围栏ID已存入Redis,key: {}, 电子围栏ID: {}", redisEfenceKey, electronicFenceRulePO.getElectronicFenceId());
|
||||
} else {
|
||||
log.warn("未找到租车规则ID为 {} 的电子围栏规则", orderMainPO.getRentCarRuleId());
|
||||
}
|
||||
|
||||
|
||||
|
||||
LambdaQueryWrapper<OrderSubPO> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.eq(OrderSubPO::getOrderId, orderMainPO.getOrderId())
|
||||
.eq(OrderSubPO::getSuborderType, SubOrderTypeEnum.RENTCAR.getCode())
|
||||
@ -1173,17 +1483,22 @@ public class OrderServiceImpl implements OrderService {
|
||||
.set(CarPO::getBrsStatus, CarStatusEnum.RENT_ING.getCode());
|
||||
carRepo.update(carPOLambdaUpdateWrapper);
|
||||
|
||||
//同步租电订单
|
||||
LambdaQueryWrapper<OrderSubPO> querySubBatteryWrapper = new LambdaQueryWrapper<>();
|
||||
querySubBatteryWrapper.eq(OrderSubPO::getOrderId, orderMainPO.getOrderId())
|
||||
.eq(OrderSubPO::getSuborderType, SubOrderTypeEnum.RENTBATTEY.getCode())
|
||||
.orderByDesc(OrderSubPO::getCreatedAt)
|
||||
.last(" limit 1");
|
||||
OrderSubPO renBatteryOrderSubPO = orderSubRepo.getOne(querySubBatteryWrapper);
|
||||
if(renBatteryOrderSubPO!=null){
|
||||
Long batterySubOrderId = renBatteryOrderSubPO.getSuborderId();
|
||||
syncInteg.sendSubOrderId(batterySubOrderId);
|
||||
ThreadPoolUtils.getThreadPool().execute(() -> {
|
||||
try {
|
||||
Map<String, String> result = syncInteg.sendSubOrderId(renBatteryOrderSubPO.getSuborderId());
|
||||
String status = result.get("code");
|
||||
if (status.equals("40001") || status.equals("40002") || status.equals("40003") || status.equals("40005") || status.equals("40006")){
|
||||
log.warn("租电订单同步失败,用户在租电APP还有未完成的订单,subOrderId: {}", renBatteryOrderSubPO.getSuborderId());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("异步同步租电订单异常,subOrderId: {}", renBatteryOrderSubPO.getSuborderId(), e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
return getOrderInfoByOrderNo(bindCarToOrderReq.getOrderNo());
|
||||
} catch (Exception e){
|
||||
log.warn("绑定车辆失败",e);
|
||||
@ -1245,6 +1560,8 @@ public class OrderServiceImpl implements OrderService {
|
||||
updateWrapper.eq(OrderMainPO::getOrderNo, bindCarToOrderReq.getOrderNo());
|
||||
orderMainRepo.update(updateWrapper);
|
||||
|
||||
|
||||
|
||||
if(!CollectionUtils.isEmpty(bindCarToOrderReq.getImageList())){
|
||||
//添加车辆图片
|
||||
List<OrderCarImgPO> carImagePOList = new ArrayList<>();
|
||||
@ -1271,7 +1588,18 @@ public class OrderServiceImpl implements OrderService {
|
||||
.set(CarPO::getBrsStatus, CarStatusEnum.NORMAL.getCode());
|
||||
carRepo.update(oldCarPOLambdaUpdateWrapper);
|
||||
|
||||
//更新电子围栏
|
||||
LambdaUpdateWrapper<CarPO> oldCarIotPOLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
|
||||
oldCarIotPOLambdaUpdateWrapper.eq(CarPO::getId, orderMainPO.getVehicleId());
|
||||
CarPO oldCarPO = carRepo.getOne(oldCarIotPOLambdaUpdateWrapper);
|
||||
|
||||
String redisEfenceKey = RedisKeyConstants.E_Fence_KEY + oldCarPO.getLotNumber();
|
||||
if(redisUtil.get(redisEfenceKey) != null){
|
||||
String efence = redisUtil.get(redisEfenceKey);
|
||||
String newKey = RedisKeyConstants.E_Fence_KEY + carDTO.getLotNumber();
|
||||
redisUtil.delete(redisEfenceKey);
|
||||
redisUtil.set(newKey, efence);
|
||||
}
|
||||
|
||||
//记录变更记录
|
||||
OrderCarChangePO orderCarChangePO = new OrderCarChangePO();
|
||||
@ -1332,6 +1660,7 @@ public class OrderServiceImpl implements OrderService {
|
||||
LambdaUpdateWrapper<OrderMainPO> updateWrapper = new LambdaUpdateWrapper<>();
|
||||
updateWrapper.set(OrderMainPO::getOrderStatus, OrderStatusEnum.AUTO_END.getCode());
|
||||
updateWrapper.set(OrderMainPO::getActEndRentTime, LocalDateTime.now());
|
||||
updateWrapper.set(OrderMainPO::getEndOrderTime, LocalDateTime.now());
|
||||
updateWrapper.set(Objects.nonNull(returnCarReq.getDamageAmount()),OrderMainPO::getDamageAmount, returnCarReq.getDamageAmount());
|
||||
updateWrapper.set(StringUtils.isNotBlank(returnCarReq.getDamageDesc()),OrderMainPO::getDamageDesc, returnCarReq.getDamageDesc());
|
||||
updateWrapper.set(rentalDuration != null,OrderMainPO::getRentalDuration, rentalDuration);
|
||||
@ -1361,6 +1690,13 @@ public class OrderServiceImpl implements OrderService {
|
||||
carPOLambdaUpdateWrapper.eq(CarPO::getId, orderDTO.getVehicleId())
|
||||
.set(CarPO::getBrsStatus, CarStatusEnum.NORMAL.getCode());
|
||||
carRepo.update(carPOLambdaUpdateWrapper);
|
||||
//删除车辆电子围栏缓存
|
||||
String redisEfenceKey = RedisKeyConstants.E_Fence_KEY + carPO.getLotNumber();
|
||||
if (redisUtil.get(redisEfenceKey) != null){
|
||||
redisUtil.deleteRedisLock(redisEfenceKey);
|
||||
}
|
||||
|
||||
|
||||
//异步执行分润
|
||||
ThreadPoolUtils.getThreadPool().execute(() -> {
|
||||
orderDistribService.saveOrderDistrib(returnCarReq.getOrderNo());
|
||||
@ -1398,7 +1734,7 @@ public class OrderServiceImpl implements OrderService {
|
||||
.eq(OrderSubPO::getPayStatus, PayStatusEnum.SUCCESS).last(" limit 1");
|
||||
OrderSubPO noDepositOrder = orderSubRepo.getOne(orderSubWrapper);
|
||||
if (Objects.nonNull(noDepositOrder)) {
|
||||
boolean result = payService.finishFreezeOrder(orderDTO.getOperatorId(),noDepositOrder.getPaymentId(),noDepositOrder.getTransactionId());
|
||||
boolean result = payService.finishFreezeOrder(orderDTO.getOperatorId(),noDepositOrder.getPaymentId(),noDepositOrder.getTransactionId(),noDepositOrder.getAmount());
|
||||
if (result) {
|
||||
//解冻成功更新状态为解冻成功
|
||||
LambdaUpdateWrapper<OrderSubPO> updatenoDepositWrapper = new LambdaUpdateWrapper<>();
|
||||
@ -1486,8 +1822,7 @@ public class OrderServiceImpl implements OrderService {
|
||||
updateWrapper.eq(OrderSubPO::getPaymentId, orderSubList.get(0).getPaymentId());
|
||||
orderSubRepo.update(updateWrapper);
|
||||
|
||||
//租车订单
|
||||
OrderSubPO rentSubPO = orderSubList.stream().filter(orderSubPO -> SubOrderTypeEnum.RENTCAR.getCode().equalsIgnoreCase(orderSubPO.getSuborderType())).findFirst().orElse( null);
|
||||
|
||||
|
||||
LambdaUpdateWrapper<OrderMainPO> updateWrapper2 = new LambdaUpdateWrapper<>();
|
||||
updateWrapper2.eq(OrderMainPO::getOrderId, orderMainPO.getOrderId());
|
||||
@ -1495,6 +1830,8 @@ public class OrderServiceImpl implements OrderService {
|
||||
updateWrapper2.set(OrderMainPO::getOrderStatus, OrderStatusEnum.WAIT_PICK.getCode());
|
||||
orderStatus = OrderStatusEnum.WAIT_PICK.getCode();
|
||||
} else if(OrderStatusEnum.RERENT_WAIT_PAY.getCode().equalsIgnoreCase(orderMainPO.getOrderStatus())){
|
||||
//租车订单
|
||||
OrderSubPO rentSubPO = orderSubList.stream().filter(orderSubPO -> SubOrderTypeEnum.RENTCAR.getCode().equalsIgnoreCase(orderSubPO.getSuborderType())).findFirst().orElse( null);
|
||||
BigDecimal rentCarOrderAmount = orderSubList.stream().map(OrderSubPO::getAmount).reduce(BigDecimal.ZERO,BigDecimal::add);
|
||||
updateWrapper2.set(OrderMainPO::getOrderAmount, orderMainPO.getOrderAmount().add(rentCarOrderAmount));
|
||||
if(rentSubPO!=null){
|
||||
@ -1505,11 +1842,18 @@ public class OrderServiceImpl implements OrderService {
|
||||
updateWrapper2.set(OrderMainPO::getOverdueDays, 0);
|
||||
}
|
||||
orderStatus = OrderStatusEnum.RENT_ING.getCode();
|
||||
//如果是续租订单,增加续租次数
|
||||
if(rentSubPO!=null){
|
||||
updateWrapper2.set(OrderMainPO::getRenewalTimes, orderMainPO.getRenewalTimes()+1);
|
||||
}
|
||||
//异步同步租电订单
|
||||
orderSubList.stream().filter(orderSubPO -> SubOrderTypeEnum.RENTBATTEY.getCode().equalsIgnoreCase(orderSubPO.getSuborderType())).findFirst()
|
||||
.ifPresent(rentBatteySubPO -> ThreadPoolUtils.getThreadPool().execute(() -> {
|
||||
Long batterySubOrderId = rentBatteySubPO.getSuborderId();
|
||||
syncInteg.sendSubOrderId(batterySubOrderId);
|
||||
}));
|
||||
}
|
||||
//如果是续租订单,增加续租次数
|
||||
if(rentSubPO!=null){
|
||||
updateWrapper2.set(OrderMainPO::getRenewalTimes, orderMainPO.getRenewalTimes()+1);
|
||||
}
|
||||
|
||||
orderMainRepo.update(updateWrapper2);
|
||||
return orderStatus;
|
||||
}
|
||||
|
||||
@ -89,6 +89,20 @@ public class PayServiceImpl implements PayService {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UnifiedPaymentInfoDTO zhimaPayOrder(String body, Long companyId, String outTradeNo, String authNo, String aliPayOpenId,BigDecimal totalFee) {
|
||||
AlipayCreateRequest alipayCreateRequest = new AlipayCreateRequest();
|
||||
alipayCreateRequest.setCompanyId(companyId);
|
||||
alipayCreateRequest.setSubject(body);
|
||||
alipayCreateRequest.setBody(body);
|
||||
alipayCreateRequest.setOutTradeNo(outTradeNo);
|
||||
alipayCreateRequest.setAuthNo(authNo);
|
||||
alipayCreateRequest.setOpenId(aliPayOpenId);
|
||||
alipayCreateRequest.setTotalAmount(totalFee.toString());
|
||||
return payInteg.zhiMaOrder(alipayCreateRequest);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public UnifiedPaymentInfoDTO freezeOrder(Long companyId, String outOrderNo, BigDecimal freezeFee) {
|
||||
AlipayFundFreezeRequest request = new AlipayFundFreezeRequest();
|
||||
@ -103,12 +117,13 @@ public class PayServiceImpl implements PayService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean finishFreezeOrder(Long companyId, String outOrderNo, String authCode) {
|
||||
public boolean finishFreezeOrder(Long companyId, String outOrderNo, String authCode, BigDecimal freezeFee) {
|
||||
log.info("开始完结支付宝押金冻结支付单");
|
||||
AlipayFinishFreezeRequest finishFreezeRequest = new AlipayFinishFreezeRequest();
|
||||
finishFreezeRequest.setCompanyId(companyId.toString());
|
||||
finishFreezeRequest.setAuthNo(authCode);
|
||||
finishFreezeRequest.setOutRequestNo(OrderUtil.generateSubOrderNo(OrderUtil.FFZ_PREFIX));
|
||||
finishFreezeRequest.setAmount(freezeFee.toString());
|
||||
AlipayResponse alipayResponse = payInteg.finishFreeze(finishFreezeRequest);
|
||||
return alipayResponse.isSuccess();
|
||||
}
|
||||
|
||||
@ -118,9 +118,10 @@ public class NoPayOrderProcessTask {
|
||||
orderProcessPO.setRetryNum(1);
|
||||
orderProcessRepo.save(orderProcessPO);
|
||||
}else {
|
||||
orderProcessPO.setRetryNum(orderProcessPO.getRetryNum()+1);
|
||||
LambdaUpdateWrapper<OrderProcessPO> updateWrapper = new LambdaUpdateWrapper<>();
|
||||
updateWrapper.eq(OrderProcessPO::getId, orderProcessPO.getId())
|
||||
.set(OrderProcessPO::getRetryNum, orderProcessPO.getRetryNum()+1);
|
||||
.set(OrderProcessPO::getRetryNum, orderProcessPO.getRetryNum());
|
||||
orderProcessRepo.update(updateWrapper);
|
||||
}
|
||||
|
||||
@ -128,9 +129,16 @@ public class NoPayOrderProcessTask {
|
||||
log.info("订单{}已超过最大重试次数,强行删除订单", orderMainPO.getOrderNo());
|
||||
orderService.forceRemoveRentOrder(orderMainPO);
|
||||
} else {
|
||||
PayOrderReq payOrderReq = new PayOrderReq();
|
||||
payOrderReq.setOrderNo(orderMainPO.getOrderNo());
|
||||
orderService.cancelOrder(payOrderReq,orderMainPO);
|
||||
if(orderMainPO.getOrderStatus().equals(OrderStatusEnum.WAIT_PAY.getCode())){
|
||||
PayOrderReq payOrderReq = new PayOrderReq();
|
||||
payOrderReq.setOrderNo(orderMainPO.getOrderNo());
|
||||
orderService.cancelOrder(payOrderReq,orderMainPO);
|
||||
} else if(orderMainPO.getOrderStatus().equals(OrderStatusEnum.RERENT_WAIT_PAY.getCode())){
|
||||
PayOrderReq payOrderReq = new PayOrderReq();
|
||||
payOrderReq.setOrderNo(orderMainPO.getOrderNo());
|
||||
orderService.cancelRerentOrOverDueOrder(orderMainPO);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -118,9 +118,10 @@ public class RefundSubOrderProcessTask {
|
||||
orderProcessPO.setRetryNum(1);
|
||||
orderProcessRepo.save(orderProcessPO);
|
||||
}else {
|
||||
orderProcessPO.setRetryNum(orderProcessPO.getRetryNum()+1);
|
||||
LambdaUpdateWrapper<OrderProcessPO> updateWrapper = new LambdaUpdateWrapper<>();
|
||||
updateWrapper.eq(OrderProcessPO::getId, orderProcessPO.getId())
|
||||
.set(OrderProcessPO::getRetryNum, orderProcessPO.getRetryNum()+1);
|
||||
.set(OrderProcessPO::getRetryNum, orderProcessPO.getRetryNum());
|
||||
orderProcessRepo.update(updateWrapper);
|
||||
}
|
||||
if(orderProcessPO.getRetryNum()>5){
|
||||
@ -142,6 +143,7 @@ public class RefundSubOrderProcessTask {
|
||||
AlipayRefundRequest request = new AlipayRefundRequest();
|
||||
request.setOutTradeNo(subPO.getPaymentId());
|
||||
request.setCompanyId(orderMainPO.getOperatorId());
|
||||
request.setOutRequestNo(subPO.getRefundId());
|
||||
AlipayResponse alipayResponse = payInteg.alipayRefundQuery(request);
|
||||
fundResult = "SUCCESS".equals(alipayResponse.getCode());
|
||||
}
|
||||
|
||||
@ -65,4 +65,10 @@ public class CompanyStoreDTO {
|
||||
|
||||
@ApiModelProperty("以租代售分成比例")
|
||||
private BigDecimal daishouRatio;
|
||||
|
||||
@ApiModelProperty("美团token")
|
||||
private String mtToken;
|
||||
|
||||
@ApiModelProperty("抖音门店id")
|
||||
private String dyStoreId;
|
||||
}
|
||||
|
||||
@ -11,4 +11,5 @@ public class AlipayCreateRequest {
|
||||
private String totalAmount; // 订单总金额
|
||||
private String body; // 订单描述
|
||||
private String openId; // 用户ID
|
||||
private String authNo; //支付宝资金授权操作处理号
|
||||
}
|
||||
|
||||
@ -0,0 +1,18 @@
|
||||
package com.sczx.order.thirdpart.dto.req;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
@ApiModel(value = "分润收入查询参数")
|
||||
@Data
|
||||
public class DistibIncomeReq {
|
||||
|
||||
@ApiModelProperty("门店id")
|
||||
private Long storeId;
|
||||
|
||||
@ApiModelProperty("金额")
|
||||
private BigDecimal amount ;
|
||||
}
|
||||
@ -60,6 +60,12 @@ public interface PayFacade {
|
||||
@PostMapping("/api/alipay/unifiedOrder")
|
||||
AlipayCreateResponse alipayUnifiedOrder(@RequestBody AlipayCreateRequest request);
|
||||
|
||||
/**
|
||||
* 支付宝统一下单接口
|
||||
*/
|
||||
@PostMapping("/api/alipay/zhiMaOrder")
|
||||
AlipayCreateResponse zhiMaOrder(@RequestBody AlipayCreateRequest request);
|
||||
|
||||
/**
|
||||
* 查询订单接口
|
||||
*/
|
||||
|
||||
@ -5,6 +5,7 @@ import com.sczx.order.thirdpart.dto.CompanyDTO;
|
||||
import com.sczx.order.thirdpart.dto.CompanyStoreDTO;
|
||||
import com.sczx.order.thirdpart.dto.SysConfigDTO;
|
||||
import com.sczx.order.thirdpart.dto.SysDictDataDTO;
|
||||
import com.sczx.order.thirdpart.dto.req.DistibIncomeReq;
|
||||
import org.springframework.cloud.openfeign.FeignClient;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
@ -32,4 +33,10 @@ public interface StoreFacade {
|
||||
|
||||
@GetMapping("/sys/getConfigByConfigKey")
|
||||
Result<SysConfigDTO> getConfigByConfigKey(@RequestParam(name = "configKey") String configKey);
|
||||
|
||||
@PostMapping("/wallet/distibIncome")
|
||||
Result<Boolean> distibIncome(@RequestBody DistibIncomeReq distibIncomeReq);
|
||||
|
||||
@PostMapping("/store/recordToken")
|
||||
Result<Boolean> recordToken(@RequestParam(name = "storeNumber") String storeNumber, @RequestParam(name = "token") String token);
|
||||
}
|
||||
|
||||
@ -12,4 +12,7 @@ public interface SyncFacade {
|
||||
@GetMapping("/send/subOrder/{subOrderId}")
|
||||
Map<String, String> sendSubOrderId(@PathVariable Long subOrderId);
|
||||
|
||||
@GetMapping("/send/OrderMeal/{subOrderId}")
|
||||
Map<String, String> sendUserMeal(@PathVariable Long subOrderId);
|
||||
|
||||
}
|
||||
@ -1,6 +1,7 @@
|
||||
package com.sczx.order.thirdpart.facade;
|
||||
|
||||
import com.sczx.order.common.Result;
|
||||
import com.sczx.order.dto.SimpleUserInfoDTO;
|
||||
import com.sczx.order.thirdpart.dto.BaseUserReferralDTO;
|
||||
import org.springframework.cloud.openfeign.FeignClient;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
@ -11,4 +12,7 @@ public interface UserFacade {
|
||||
|
||||
@GetMapping("/referral/getUserReferralByUserId")
|
||||
Result<BaseUserReferralDTO> getUserReferralByUserId(@RequestParam("userId") Long userId);
|
||||
|
||||
@GetMapping("/auth/getUInfoByMobile")
|
||||
Result<SimpleUserInfoDTO> getUInfoByMobile(@RequestParam("mobile") String mobile);
|
||||
}
|
||||
|
||||
@ -152,6 +152,26 @@ public class PayInteg {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 支付宝免押扣款接口
|
||||
*/
|
||||
public UnifiedPaymentInfoDTO zhiMaOrder(AlipayCreateRequest request){
|
||||
try {
|
||||
AlipayCreateResponse result = payFacade.zhiMaOrder(request);
|
||||
if(StringUtils.isNotBlank(result.getCode()) && "SUCCESS".equals(result.getCode())){
|
||||
UnifiedPaymentInfoDTO unifiedPaymentInfo = new UnifiedPaymentInfoDTO();
|
||||
unifiedPaymentInfo.setOutTradeNo(result.getOutTradeNo());
|
||||
unifiedPaymentInfo.setTradeNo(result.getTradeNo());
|
||||
return unifiedPaymentInfo;
|
||||
}else {
|
||||
throw new InnerException("支付宝免押扣款失败");
|
||||
}
|
||||
} catch (Exception e){
|
||||
log.error("支付宝免押扣款失败",e);
|
||||
throw new InnerException("支付宝免押扣款失败");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询订单接口
|
||||
*/
|
||||
|
||||
@ -6,6 +6,7 @@ import com.sczx.order.thirdpart.dto.CompanyDTO;
|
||||
import com.sczx.order.thirdpart.dto.CompanyStoreDTO;
|
||||
import com.sczx.order.thirdpart.dto.SysConfigDTO;
|
||||
import com.sczx.order.thirdpart.dto.SysDictDataDTO;
|
||||
import com.sczx.order.thirdpart.dto.req.DistibIncomeReq;
|
||||
import com.sczx.order.thirdpart.facade.StoreFacade;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@ -86,4 +87,36 @@ public class StoreInteg {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 分润收入
|
||||
* @param distibIncomeReq
|
||||
* @return
|
||||
*/
|
||||
public boolean distibIncome(DistibIncomeReq distibIncomeReq){
|
||||
|
||||
try{
|
||||
Result<Boolean> result = storeFacade.distibIncome(distibIncomeReq);
|
||||
if(result.isSuccess()){
|
||||
return result.getData();
|
||||
}
|
||||
} catch (Exception e){
|
||||
log.error("分润收入失败",e);
|
||||
throw new InnerException("分润收入失败");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean recordToken(String storeNumber, String token){
|
||||
try{
|
||||
Result<Boolean> result = storeFacade.recordToken(storeNumber, token);
|
||||
if(result.isSuccess()){
|
||||
return result.getData();
|
||||
}
|
||||
} catch (Exception e){
|
||||
log.error("记录门店token失败",e);
|
||||
throw new InnerException("记录门店token失败");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -18,16 +18,29 @@ public class SyncInteg {
|
||||
public Map<String, String> sendSubOrderId(Long subOrderId){
|
||||
try{
|
||||
Map<String, String> result = syncFacade.sendSubOrderId(subOrderId);
|
||||
if(result.get("code") == "200"){
|
||||
if( "200".equals(result.get("code"))){
|
||||
return result;
|
||||
}else{
|
||||
return result;
|
||||
}
|
||||
} catch (Exception e){
|
||||
log.error("发送租电订单同步失败",e);
|
||||
throw new InnerException("发送租电订单同步失败");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public Map<String, String> sendUserMeal(Long subOrderId){
|
||||
try{
|
||||
Map<String, String> result = syncFacade.sendUserMeal(subOrderId);
|
||||
if( "200".equals(result.get("code"))){
|
||||
return result;
|
||||
}else{
|
||||
return result;
|
||||
}
|
||||
} catch (Exception e){
|
||||
log.error("发送租电订单查询失败",e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,12 +1,14 @@
|
||||
package com.sczx.order.thirdpart.integration;
|
||||
|
||||
import com.sczx.order.common.Result;
|
||||
import com.sczx.order.dto.SimpleUserInfoDTO;
|
||||
import com.sczx.order.exception.InnerException;
|
||||
import com.sczx.order.thirdpart.dto.BaseUserReferralDTO;
|
||||
import com.sczx.order.thirdpart.facade.UserFacade;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
@ -27,4 +29,17 @@ public class UserInteg {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public SimpleUserInfoDTO getUInfoByMobile(String mobile){
|
||||
try{
|
||||
Result<SimpleUserInfoDTO> result = userFacade.getUInfoByMobile(mobile);
|
||||
if(result.isSuccess()){
|
||||
return result.getData();
|
||||
}
|
||||
} catch (Exception e){
|
||||
log.error("获取用户信息失败",e);
|
||||
throw new InnerException("获取用户信息失败");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
107
src/main/java/com/sczx/order/utils/DouyinTokenManager.java
Normal file
107
src/main/java/com/sczx/order/utils/DouyinTokenManager.java
Normal file
@ -0,0 +1,107 @@
|
||||
package com.sczx.order.utils;
|
||||
|
||||
import com.aliyun.tea.TeaException;
|
||||
import com.douyin.openapi.client.Client;
|
||||
import com.douyin.openapi.client.models.OauthClientTokenRequest;
|
||||
import com.douyin.openapi.client.models.OauthClientTokenResponse;
|
||||
import com.douyin.openapi.credential.models.Config;
|
||||
|
||||
import java.util.concurrent.ScheduledThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
/**
|
||||
* 抖音 client_token 管理器
|
||||
* 负责定时获取和缓存 client_token
|
||||
*/
|
||||
public class DouyinTokenManager {
|
||||
|
||||
// 应用凭证信息
|
||||
private static final String CLIENT_KEY = "awomt6nnjlfc491m";
|
||||
private static final String CLIENT_SECRET = "c678c411c7a68c6f97969f2dbd8ef8fc";
|
||||
|
||||
// Token 缓存
|
||||
private static final AtomicReference<OauthClientTokenResponse> tokenCache =
|
||||
new AtomicReference<>();
|
||||
|
||||
// 定时任务执行器
|
||||
private static final ScheduledThreadPoolExecutor scheduler =
|
||||
new ScheduledThreadPoolExecutor(1, r -> {
|
||||
Thread t = new Thread(r, "DouyinTokenRefreshThread");
|
||||
t.setDaemon(false);
|
||||
return t;
|
||||
});
|
||||
|
||||
static {
|
||||
// 初始化时立即获取一次 token
|
||||
refreshClientToken();
|
||||
|
||||
// 每小时更新一次 token (3600秒)
|
||||
scheduler.scheduleAtFixedRate(
|
||||
DouyinTokenManager::refreshClientToken,
|
||||
3600,
|
||||
3600,
|
||||
TimeUnit.SECONDS
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前有效的 client_token
|
||||
*
|
||||
* @return 当前有效的 access_token
|
||||
*/
|
||||
public static String getCurrentToken() {
|
||||
OauthClientTokenResponse response = tokenCache.get();
|
||||
if (response != null && response.getData() != null) {
|
||||
return response.getData().getAccessToken();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 刷新 client_token
|
||||
*/
|
||||
private static void refreshClientToken() {
|
||||
try {
|
||||
Config config = new Config()
|
||||
.setClientKey(CLIENT_KEY)
|
||||
.setClientSecret(CLIENT_SECRET);
|
||||
|
||||
Client client = new Client(config);
|
||||
|
||||
OauthClientTokenRequest sdkRequest = new OauthClientTokenRequest();
|
||||
sdkRequest.setClientKey(CLIENT_KEY);
|
||||
sdkRequest.setClientSecret(CLIENT_SECRET);
|
||||
sdkRequest.setGrantType("client_credential");
|
||||
|
||||
OauthClientTokenResponse sdkResponse = client.OauthClientToken(sdkRequest);
|
||||
|
||||
// 更新缓存
|
||||
tokenCache.set(sdkResponse);
|
||||
|
||||
if (sdkResponse.getData() != null) {
|
||||
System.out.println("抖音 client_token 更新成功,有效期至: " +
|
||||
(System.currentTimeMillis() + sdkResponse.getData().getExpiresIn() * 1000));
|
||||
}
|
||||
} catch (TeaException e) {
|
||||
System.err.println("获取抖音 client_token 失败 (TeaException): " + e.getMessage());
|
||||
} catch (Exception e) {
|
||||
System.err.println("获取抖音 client_token 失败 (Exception): " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭定时任务
|
||||
*/
|
||||
public static void shutdown() {
|
||||
scheduler.shutdown();
|
||||
|
||||
// 获取当前有效的 client_token
|
||||
String token = DouyinTokenManager.getCurrentToken();
|
||||
|
||||
// 使用 token 调用抖音 API
|
||||
if (token != null) {
|
||||
// 调用订单查询等接口
|
||||
}
|
||||
}
|
||||
}
|
||||
86
src/main/java/com/sczx/order/utils/MeiTuanSignUtils.java
Normal file
86
src/main/java/com/sczx/order/utils/MeiTuanSignUtils.java
Normal file
@ -0,0 +1,86 @@
|
||||
package com.sczx.order.utils;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.security.MessageDigest;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
|
||||
@Slf4j
|
||||
public class MeiTuanSignUtils {
|
||||
private MeiTuanSignUtils() {}
|
||||
|
||||
public static String getSign(String signKey, Map<String, String> params) {
|
||||
try {
|
||||
String sortedStr = getSortedParamStr(params);
|
||||
String paraStr = signKey + sortedStr;
|
||||
|
||||
return createSign(paraStr);
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
log.warn("getSign UnsupportedEncodingException ", e);
|
||||
}
|
||||
|
||||
return StringUtils.EMPTY;
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造自然排序请求参数
|
||||
*
|
||||
* @param params 请求
|
||||
* @return 字符串
|
||||
*/
|
||||
private static String getSortedParamStr(Map<String, String> params) throws UnsupportedEncodingException {
|
||||
Set<String> sortedParams = new TreeSet<>(params.keySet());
|
||||
|
||||
StringBuilder strB = new StringBuilder();
|
||||
// 排除sign和空值参数
|
||||
for (String key : sortedParams) {
|
||||
if ("sign".equalsIgnoreCase(key)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String value = params.get(key);
|
||||
|
||||
if (StringUtils.isNotEmpty(value)) {
|
||||
strB.append(key).append(value);
|
||||
}
|
||||
}
|
||||
return strB.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成新sign
|
||||
*
|
||||
* @param str 字符串
|
||||
* @return String
|
||||
*/
|
||||
private static String createSign(String str) {
|
||||
if (str == null || str.length() == 0) {
|
||||
return null;
|
||||
}
|
||||
char[] hexDigits = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
|
||||
try {
|
||||
MessageDigest mdTemp = MessageDigest.getInstance("SHA1");
|
||||
mdTemp.update(str.getBytes("UTF-8"));
|
||||
|
||||
byte[] md = mdTemp.digest();
|
||||
int j = md.length;
|
||||
char[] buf = new char[j * 2];
|
||||
int k = 0;
|
||||
int i = 0;
|
||||
while (i < j) {
|
||||
byte byte0 = md[i];
|
||||
buf[k++] = hexDigits[byte0 >>> 4 & 0xf];
|
||||
buf[k++] = hexDigits[byte0 & 0xf];
|
||||
i++;
|
||||
}
|
||||
return new String(buf);
|
||||
} catch (Exception e) {
|
||||
log.warn("create sign was failed", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -62,8 +62,10 @@ public class OrderUtil {
|
||||
public static Integer getOrderOverdueHours(LocalDateTime endRentTime) {
|
||||
if(endRentTime!=null){
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
log.info("计算间隔小时数,预计还车时间:{}, 当前时间 : {}", endRentTime, now);
|
||||
if(now.isAfter(endRentTime)){
|
||||
return (int) ChronoUnit.HOURS.between(endRentTime, now);
|
||||
int hours = (int) ChronoUnit.HOURS.between(endRentTime, now);
|
||||
return hours +1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
@ -77,8 +79,14 @@ public class OrderUtil {
|
||||
public static Integer getOrderOverdueDays(LocalDateTime endRentTime) {
|
||||
if(endRentTime!=null){
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
log.info("计算间隔天数,预计还车时间:{}, 当前时间 : {}", endRentTime, now);
|
||||
if(now.isAfter(endRentTime)){
|
||||
return (int) ChronoUnit.DAYS.between(endRentTime, now);
|
||||
long days = ChronoUnit.DAYS.between(endRentTime, now);
|
||||
// 检查是否有不足一天的余数
|
||||
if (!now.truncatedTo(ChronoUnit.DAYS).equals(endRentTime.plusDays(days).truncatedTo(ChronoUnit.DAYS))) {
|
||||
return (int) days + 1;
|
||||
}
|
||||
return (int) days;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
@ -111,9 +119,14 @@ public class OrderUtil {
|
||||
if(startTime!=null&&endTime!=null){
|
||||
if(startTime.isBefore(endTime)){
|
||||
if(StringUtils.equalsIgnoreCase(rentalType, RentCarTypeEnum.HOUR_RENTAL.getCode())){
|
||||
return (int) ChronoUnit.HOURS.between(startTime, endTime);
|
||||
return (int) ChronoUnit.HOURS.between(startTime, endTime) +1;
|
||||
} else {
|
||||
return (int) ChronoUnit.DAYS.between(startTime, endTime);
|
||||
long days = ChronoUnit.DAYS.between(startTime, endTime) +1;
|
||||
// 检查是否有不足一天的余数
|
||||
if (!endTime.truncatedTo(ChronoUnit.DAYS).equals(endTime.plusDays(days).truncatedTo(ChronoUnit.DAYS))) {
|
||||
return (int) days + 1;
|
||||
}
|
||||
return (int) days;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -24,6 +24,10 @@ public class RedisUtil {
|
||||
redisTemplate.opsForValue().set(key, value, timeout, unit);
|
||||
}
|
||||
|
||||
public void set(String key, String value) {
|
||||
redisTemplate.opsForValue().set(key, value);
|
||||
}
|
||||
|
||||
public String get(String key) {
|
||||
return redisTemplate.opsForValue().get(key);
|
||||
}
|
||||
|
||||
BIN
src/main/resources/lib/MtOpJavaSDK-1.0-SNAPSHOT.jar
Normal file
BIN
src/main/resources/lib/MtOpJavaSDK-1.0-SNAPSHOT.jar
Normal file
Binary file not shown.
BIN
src/main/resources/lib/sdk-1.0.6.jar
Normal file
BIN
src/main/resources/lib/sdk-1.0.6.jar
Normal file
Binary file not shown.
5
src/main/resources/mapper/ElectronicFenceRuleMapper.xml
Normal file
5
src/main/resources/mapper/ElectronicFenceRuleMapper.xml
Normal file
@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.sczx.order.mapper.ElectronicFenceRuleMapper">
|
||||
|
||||
</mapper>
|
||||
@ -6,8 +6,8 @@
|
||||
SELECT
|
||||
store_id,
|
||||
COUNT(*) as total_orders,
|
||||
SUM(CASE WHEN (order_status = 'AUTO_END' OR order_status = 'MANUAL_END') AND DATE_FORMAT(end_order_time, '%Y-%m') = DATE_FORMAT(NOW(), '%Y-%m') THEN 1 ELSE 0 END) as monthly_completed_orders,
|
||||
SUM(CASE WHEN (order_status = 'AUTO_END' OR order_status = 'MANUAL_END') AND DATE_FORMAT(end_order_time, '%Y-%m') = DATE_FORMAT(NOW(), '%Y-%m') THEN order_amount ELSE 0 END) as monthly_order_amount,
|
||||
SUM(CASE WHEN (order_status = 'AUTO_END' OR order_status = 'MANUAL_END') AND DATE_FORMAT(ifnull(end_order_time,act_end_rent_time), '%Y-%m') = DATE_FORMAT(NOW(), '%Y-%m') THEN 1 ELSE 0 END) as monthly_completed_orders,
|
||||
SUM(CASE WHEN (order_status = 'AUTO_END' OR order_status = 'MANUAL_END') AND DATE_FORMAT(ifnull(end_order_time,act_end_rent_time), '%Y-%m') = DATE_FORMAT(NOW(), '%Y-%m') THEN order_amount ELSE 0 END) as monthly_order_amount,
|
||||
COUNT(CASE WHEN order_status = 'WAIT_PICK' THEN 1 END) as pending_pickup_count,
|
||||
COUNT(CASE WHEN order_status = 'WAIT_RETURN' THEN 1 END) as pending_return_count,
|
||||
COUNT(CASE WHEN order_status = 'RENT_OVERDUE' THEN 1 END) as overdue_count
|
||||
|
||||
Reference in New Issue
Block a user