feat: 添加微信小程序环境版本配置及相关功能实现

This commit is contained in:
2026-07-23 17:23:10 +08:00
parent ba9f32fd02
commit 05d68d106c
7 changed files with 586 additions and 18 deletions

View File

@@ -221,10 +221,10 @@ public class AppOutdoorFairController extends BaseController
return AjaxResult.error("招聘会不存在");
}
if (fair.getHoldTime() == null) {
return AjaxResult.error("招聘会开始时间未设置,暂不能签到");
return AjaxResult.error("招聘会还没有开始,暂不能签到");
}
if (!hasFairStarted(fair, new Date())) {
return AjaxResult.error("招聘会尚未开始,暂不能签到");
return AjaxResult.error("招聘会还没有开始,暂不能签到");
}
// 同一招聘会下同手机号已签到则不重复记录
Long exists = outdoorFairAttendeeService.count(new LambdaQueryWrapper<OutdoorFairAttendee>()

View File

@@ -42,14 +42,15 @@ public class WeChatMiniProgramApiClient
return new AccessTokenResult(accessToken, expiresIn == null ? 7200 : expiresIn);
}
public QrCodeImage getUnlimitedQrCode(String accessToken, String scene, String page)
public QrCodeImage getUnlimitedQrCode(String accessToken, String scene, String page,
String envVersion)
{
JSONObject requestBody = new JSONObject();
requestBody.put("scene", scene);
requestBody.put("page", page);
// 新页面尚未随小程序版本发布时也允许先生成码;扫码仍会进入正式版小程序。
// 新页面尚未随小程序版本发布时也允许先生成码;扫码进入配置指定的小程序版本
requestBody.put("check_path", false);
requestBody.put("env_version", "release");
requestBody.put("env_version", envVersion);
requestBody.put("width", 430);
HttpResponse response = null;

View File

@@ -18,13 +18,15 @@ import java.util.function.LongSupplier;
public class WeChatMiniProgramQrCodeService
{
public static final String OUTDOOR_FAIR_PAGE = "packageA/pages/outdoorFair/detail";
public static final String DEFAULT_ENV_VERSION = "trial";
private static final long TOKEN_REFRESH_AHEAD_MILLIS = 300_000L;
private final WeChatMiniProgramApiClient apiClient;
private final String appId;
private final String appSecret;
private final String envVersion;
private final LongSupplier currentTimeMillis;
private final Map<Long, String> qrCodeDataUrlCache = new ConcurrentHashMap<>();
private final Map<String, String> qrCodeDataUrlCache = new ConcurrentHashMap<>();
private volatile String accessToken;
private volatile long accessTokenExpiresAt;
@@ -32,17 +34,26 @@ public class WeChatMiniProgramQrCodeService
@Autowired
public WeChatMiniProgramQrCodeService(WeChatMiniProgramApiClient apiClient,
@Value("${wx.appid}") String appId,
@Value("${wx.secret}") String appSecret)
@Value("${wx.secret}") String appSecret,
@Value("${wx.env-version:trial}") String envVersion)
{
this(apiClient, appId, appSecret, System::currentTimeMillis);
this(apiClient, appId, appSecret, envVersion, System::currentTimeMillis);
}
WeChatMiniProgramQrCodeService(WeChatMiniProgramApiClient apiClient, String appId,
String appSecret, LongSupplier currentTimeMillis)
{
this(apiClient, appId, appSecret, DEFAULT_ENV_VERSION, currentTimeMillis);
}
WeChatMiniProgramQrCodeService(WeChatMiniProgramApiClient apiClient, String appId,
String appSecret, String envVersion,
LongSupplier currentTimeMillis)
{
this.apiClient = apiClient;
this.appId = appId;
this.appSecret = appSecret;
this.envVersion = normalizeEnvVersion(envVersion);
this.currentTimeMillis = currentTimeMillis;
}
@@ -52,16 +63,17 @@ public class WeChatMiniProgramQrCodeService
throw new ServiceException("招聘会参数不正确");
}
String scene = "fairId=" + fairId;
String imageData = qrCodeDataUrlCache.get(fairId);
String cacheKey = envVersion + ":" + fairId;
String imageData = qrCodeDataUrlCache.get(cacheKey);
if (imageData == null) {
synchronized (qrCodeDataUrlCache) {
imageData = qrCodeDataUrlCache.get(fairId);
imageData = qrCodeDataUrlCache.get(cacheKey);
if (imageData == null) {
WeChatMiniProgramApiClient.QrCodeImage image = apiClient.getUnlimitedQrCode(
getValidAccessToken(), scene, OUTDOOR_FAIR_PAGE);
getValidAccessToken(), scene, OUTDOOR_FAIR_PAGE, envVersion);
imageData = "data:" + image.getContentType() + ";base64,"
+ Base64.getEncoder().encodeToString(image.getContent());
qrCodeDataUrlCache.put(fairId, imageData);
qrCodeDataUrlCache.put(cacheKey, imageData);
}
}
}
@@ -70,6 +82,7 @@ public class WeChatMiniProgramQrCodeService
data.put("fairId", fairId);
data.put("page", OUTDOOR_FAIR_PAGE);
data.put("scene", scene);
data.put("envVersion", envVersion);
data.put("imageData", imageData);
// getUnlimitedQRCode 生成的小程序码长期有效;需要轮换的是 access token而不是已经生成的码。
data.put("permanent", true);
@@ -77,6 +90,20 @@ public class WeChatMiniProgramQrCodeService
return data;
}
private String normalizeEnvVersion(String value)
{
String normalized = value == null ? "" : value.trim().toLowerCase();
if (normalized.isEmpty()) {
return DEFAULT_ENV_VERSION;
}
if (!"trial".equals(normalized)
&& !"release".equals(normalized)
&& !"develop".equals(normalized)) {
throw new ServiceException("微信小程序版本配置不正确,仅支持 trial、release 或 develop");
}
return normalized;
}
private String getValidAccessToken()
{
long now = currentTimeMillis.getAsLong();