|
@@ -1,6 +1,7 @@
|
|
|
package com.kym.miniapp.controller;
|
|
package com.kym.miniapp.controller;
|
|
|
|
|
|
|
|
import cn.dev33.satoken.annotation.SaIgnore;
|
|
import cn.dev33.satoken.annotation.SaIgnore;
|
|
|
|
|
+import com.kym.common.exception.BusinessException;
|
|
|
import com.kym.common.utils.HttpUtil;
|
|
import com.kym.common.utils.HttpUtil;
|
|
|
import com.kym.entity.ParkingCouponRecord;
|
|
import com.kym.entity.ParkingCouponRecord;
|
|
|
import com.kym.entity.User;
|
|
import com.kym.entity.User;
|
|
@@ -14,11 +15,13 @@ import com.kym.common.R;
|
|
|
import jakarta.servlet.http.HttpServletResponse;
|
|
import jakarta.servlet.http.HttpServletResponse;
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
import org.springframework.beans.factory.annotation.Value;
|
|
import org.springframework.beans.factory.annotation.Value;
|
|
|
|
|
+import org.springframework.core.env.Environment;
|
|
|
import org.springframework.web.bind.annotation.*;
|
|
import org.springframework.web.bind.annotation.*;
|
|
|
|
|
|
|
|
import java.io.IOException;
|
|
import java.io.IOException;
|
|
|
import java.net.URL;
|
|
import java.net.URL;
|
|
|
import java.time.LocalDateTime;
|
|
import java.time.LocalDateTime;
|
|
|
|
|
+import java.util.Arrays;
|
|
|
import java.util.UUID;
|
|
import java.util.UUID;
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -37,6 +40,7 @@ public class ParkingCouponController {
|
|
|
private final MpMsgTemplateService mpMsgTemplateService;
|
|
private final MpMsgTemplateService mpMsgTemplateService;
|
|
|
private final UserService userService;
|
|
private final UserService userService;
|
|
|
private final ParkingCouponRecordService parkingCouponRecordService;
|
|
private final ParkingCouponRecordService parkingCouponRecordService;
|
|
|
|
|
+ private final Environment environment;
|
|
|
|
|
|
|
|
@Value("${kym.domain}")
|
|
@Value("${kym.domain}")
|
|
|
private String DOMAIN;
|
|
private String DOMAIN;
|
|
@@ -44,11 +48,13 @@ public class ParkingCouponController {
|
|
|
public ParkingCouponController(WashOrderService washOrderService,
|
|
public ParkingCouponController(WashOrderService washOrderService,
|
|
|
MpMsgTemplateService mpMsgTemplateService,
|
|
MpMsgTemplateService mpMsgTemplateService,
|
|
|
UserService userService,
|
|
UserService userService,
|
|
|
- ParkingCouponRecordService parkingCouponRecordService) {
|
|
|
|
|
|
|
+ ParkingCouponRecordService parkingCouponRecordService,
|
|
|
|
|
+ Environment environment) {
|
|
|
this.washOrderService = washOrderService;
|
|
this.washOrderService = washOrderService;
|
|
|
this.mpMsgTemplateService = mpMsgTemplateService;
|
|
this.mpMsgTemplateService = mpMsgTemplateService;
|
|
|
this.userService = userService;
|
|
this.userService = userService;
|
|
|
this.parkingCouponRecordService = parkingCouponRecordService;
|
|
this.parkingCouponRecordService = parkingCouponRecordService;
|
|
|
|
|
+ this.environment = environment;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -74,11 +80,16 @@ public class ParkingCouponController {
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- parkingCouponRecordService.lambdaUpdate()
|
|
|
|
|
|
|
+ // 原子核销:仅当状态为未使用时置为已使用,重复点击/并发点击不会重复核销
|
|
|
|
|
+ boolean consumed = parkingCouponRecordService.lambdaUpdate()
|
|
|
.eq(ParkingCouponRecord::getCode, code)
|
|
.eq(ParkingCouponRecord::getCode, code)
|
|
|
|
|
+ .eq(ParkingCouponRecord::getStatus, ParkingCouponRecord.STATUS_未使用)
|
|
|
.set(ParkingCouponRecord::getStatus, ParkingCouponRecord.STATUS_已使用)
|
|
.set(ParkingCouponRecord::getStatus, ParkingCouponRecord.STATUS_已使用)
|
|
|
.set(ParkingCouponRecord::getUsedTime, LocalDateTime.now())
|
|
.set(ParkingCouponRecord::getUsedTime, LocalDateTime.now())
|
|
|
.update();
|
|
.update();
|
|
|
|
|
+ if (!consumed) {
|
|
|
|
|
+ log.info("停车券 {} 已核销或不存在,跳过状态更新", code);
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
if (url.length() < MAX_REDIRECT_URL_LENGTH) {
|
|
if (url.length() < MAX_REDIRECT_URL_LENGTH) {
|
|
|
log.info("短 URL 直接重定向, code: {}, urlLength: {}", code, url.length());
|
|
log.info("短 URL 直接重定向, code: {}, urlLength: {}", code, url.length());
|
|
@@ -119,19 +130,23 @@ public class ParkingCouponController {
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
* [测试] 生成停车券短链接,返回 url 可直接在浏览器打开测试
|
|
* [测试] 生成停车券短链接,返回 url 可直接在浏览器打开测试
|
|
|
|
|
+ * 仅限开发环境(dev/test/local profile)注册,生产环境不可用
|
|
|
*/
|
|
*/
|
|
|
@SaIgnore
|
|
@SaIgnore
|
|
|
@GetMapping("/testLink")
|
|
@GetMapping("/testLink")
|
|
|
public R<String> testLink(@RequestParam String mobilePhone) {
|
|
public R<String> testLink(@RequestParam String mobilePhone) {
|
|
|
|
|
+ assertDevEnv();
|
|
|
return R.success(washOrderService.checkParkingCoupon(mobilePhone));
|
|
return R.success(washOrderService.checkParkingCoupon(mobilePhone));
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
* [测试] 发送停车券微信模板消息,需要用户已关注公众号且有 mpOpenid
|
|
* [测试] 发送停车券微信模板消息,需要用户已关注公众号且有 mpOpenid
|
|
|
|
|
+ * 仅限开发环境(dev/test/local profile)注册,生产环境不可用
|
|
|
*/
|
|
*/
|
|
|
@SaIgnore
|
|
@SaIgnore
|
|
|
@GetMapping("/testSend")
|
|
@GetMapping("/testSend")
|
|
|
public String testSend(@RequestParam String mobilePhone) {
|
|
public String testSend(@RequestParam String mobilePhone) {
|
|
|
|
|
+ assertDevEnv();
|
|
|
var user = userService.lambdaQuery().eq(User::getMobilePhone, mobilePhone).one();
|
|
var user = userService.lambdaQuery().eq(User::getMobilePhone, mobilePhone).one();
|
|
|
if (user == null) {
|
|
if (user == null) {
|
|
|
return "用户不存在: " + mobilePhone;
|
|
return "用户不存在: " + mobilePhone;
|
|
@@ -153,6 +168,18 @@ public class ParkingCouponController {
|
|
|
return "已发送, url=" + url;
|
|
return "已发送, url=" + url;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 测试接口仅限开发环境:通过 active profile 判断(dev/test/local)
|
|
|
|
|
+ */
|
|
|
|
|
+ private void assertDevEnv() {
|
|
|
|
|
+ var profiles = environment.getActiveProfiles();
|
|
|
|
|
+ boolean dev = profiles != null && Arrays.stream(profiles)
|
|
|
|
|
+ .anyMatch(p -> "dev".equals(p) || "test".equals(p) || "local".equals(p));
|
|
|
|
|
+ if (!dev) {
|
|
|
|
|
+ throw new BusinessException("测试接口仅限开发环境使用");
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
private static String extractOrigin(String url) {
|
|
private static String extractOrigin(String url) {
|
|
|
try {
|
|
try {
|
|
|
URL u = new URL(url);
|
|
URL u = new URL(url);
|