package com.ruoyi.account.task;
|
|
import com.alibaba.fastjson2.JSON;
|
import com.alibaba.fastjson2.JSONObject;
|
import com.ruoyi.account.api.model.TAppUser;
|
import com.ruoyi.account.api.model.TAppUserSiteFavorite;
|
import com.ruoyi.account.service.TAppUserService;
|
import com.ruoyi.account.service.TAppUserSiteFavoriteService;
|
import com.ruoyi.account.wx.model.WeixinProperties;
|
import com.ruoyi.account.wx.tools.WxAppletTools;
|
import com.ruoyi.chargingPile.api.feignClient.SiteClient;
|
import com.ruoyi.chargingPile.api.vo.FavoriteSitePriceVO;
|
import com.ruoyi.common.core.domain.R;
|
import com.ruoyi.common.core.utils.HttpUtils;
|
import com.ruoyi.common.redis.service.RedisService;
|
import lombok.extern.slf4j.Slf4j;
|
import org.redisson.api.RLock;
|
import org.redisson.api.RedissonClient;
|
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.scheduling.annotation.Scheduled;
|
import org.springframework.stereotype.Component;
|
import org.springframework.util.StringUtils;
|
import org.springframework.web.client.RestTemplate;
|
|
import javax.annotation.Resource;
|
import java.math.BigDecimal;
|
import java.util.Collections;
|
import java.util.List;
|
import java.util.Map;
|
import java.util.Objects;
|
import java.util.concurrent.TimeUnit;
|
import java.util.function.Function;
|
import java.util.stream.Collectors;
|
|
@Slf4j
|
@Component
|
public class FavoritePriceDropTask {
|
|
private static final String SEND_URL = "https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=";
|
|
@Resource
|
private TAppUserSiteFavoriteService favoriteService;
|
@Resource
|
private TAppUserService appUserService;
|
@Resource
|
private SiteClient siteClient;
|
@Resource
|
private RestTemplate wxRestTemplate;
|
@Resource
|
private WeixinProperties wxConfig;
|
@Resource
|
private RedisService redisService;
|
@Resource
|
private RedissonClient redissonClient;
|
|
@Value("${wx.applet.price-drop-template-id:7nCycRUZxQ2jxAb2UaYazjp2sPZy3qYyeLqVytyhHhY}")
|
private String templateId;
|
|
@Value("${wx.applet.price-drop-page:pagesMine/favoriteSite/favoriteSite}")
|
private String page;
|
|
@Scheduled(fixedDelay = 30 * 60 * 1000L, initialDelay = 2 * 60 * 1000L)
|
public void notifyPriceDrop() {
|
if (!StringUtils.hasText(templateId)) {
|
return;
|
}
|
RLock lock = redissonClient.getLock("FAVORITE_SITE_PRICE_DROP_TASK");
|
boolean locked = false;
|
try {
|
locked = lock.tryLock(0, 10, TimeUnit.MINUTES);
|
if (!locked) {
|
return;
|
}
|
List<TAppUserSiteFavorite> favorites = favoriteService.lambdaQuery()
|
.eq(TAppUserSiteFavorite::getNotifyEnabled, true)
|
.list();
|
if (favorites.isEmpty()) {
|
return;
|
}
|
List<Integer> siteIds = favorites.stream().map(TAppUserSiteFavorite::getSiteId)
|
.filter(Objects::nonNull).distinct().collect(Collectors.toList());
|
R<List<FavoriteSitePriceVO>> response = siteClient.getFavoriteSitePrices(siteIds);
|
List<FavoriteSitePriceVO> prices = response == null || response.getData() == null
|
? Collections.emptyList() : response.getData();
|
Map<Integer, FavoriteSitePriceVO> priceMap = prices.stream()
|
.collect(Collectors.toMap(FavoriteSitePriceVO::getSiteId, Function.identity(), (a, b) -> a));
|
for (TAppUserSiteFavorite favorite : favorites) {
|
FavoriteSitePriceVO price = priceMap.get(favorite.getSiteId());
|
if (price == null || price.getCurrentPrice() == null || favorite.getFavoritePrice() == null
|
|| price.getCurrentPrice().compareTo(favorite.getFavoritePrice()) >= 0) {
|
continue;
|
}
|
TAppUser user = appUserService.getById(favorite.getAppUserId());
|
if (user == null || !StringUtils.hasText(user.getWxOpenid())) {
|
log.info("收藏站点降价提醒未发送,用户openid为空,userId={}, siteId={}",
|
favorite.getAppUserId(), favorite.getSiteId());
|
continue;
|
}
|
if (sendSubscribeMessage(user.getWxOpenid(), favorite, price)) {
|
favorite.setNotifyEnabled(false);
|
favorite.setLastNotifiedPrice(price.getCurrentPrice());
|
favoriteService.updateById(favorite);
|
log.info("收藏站点降价提醒发送成功,userId={}, siteId={}, currentPrice={}",
|
favorite.getAppUserId(), favorite.getSiteId(), price.getCurrentPrice());
|
}
|
}
|
} catch (InterruptedException e) {
|
Thread.currentThread().interrupt();
|
} catch (Exception e) {
|
log.error("收藏站点降价提醒任务执行失败", e);
|
} finally {
|
if (locked && lock.isHeldByCurrentThread()) {
|
lock.unlock();
|
}
|
}
|
}
|
|
private boolean sendSubscribeMessage(String openId, TAppUserSiteFavorite favorite, FavoriteSitePriceVO price) {
|
JSONObject body = new JSONObject();
|
body.put("touser", openId);
|
body.put("template_id", templateId);
|
body.put("page", page + "?siteId=" + favorite.getSiteId());
|
JSONObject data = new JSONObject();
|
data.put("thing1", value(limit(price.getSiteName(), 20)));
|
data.put("amount4", value(formatAmount(price.getCurrentPrice())));
|
body.put("data", data);
|
String accessToken = new WxAppletTools(wxRestTemplate, wxConfig, redisService).getAccessToken("");
|
String result = HttpUtils.post(SEND_URL + accessToken, body.toJSONString());
|
JSONObject response = JSON.parseObject(result);
|
boolean success = response != null && response.getIntValue("errcode") == 0;
|
if (!success) {
|
log.warn("发送收藏站点降价提醒失败,userId={}, siteId={}, response={}",
|
favorite.getAppUserId(), favorite.getSiteId(), result);
|
}
|
return success;
|
}
|
|
private JSONObject value(String value) {
|
JSONObject item = new JSONObject();
|
item.put("value", value);
|
return item;
|
}
|
|
private String formatAmount(BigDecimal amount) {
|
return amount.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString() + "元";
|
}
|
|
private String limit(String value, int length) {
|
if (!StringUtils.hasText(value) || value.length() <= length) {
|
return value;
|
}
|
return value.substring(0, length);
|
}
|
}
|