puzhibing
4 天以前 3650ce7f5d42d1bef58abea9693f20d1f209d3b0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
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;
 
    // 降价推送已改为计费策略审批通过时触发(TAccountingStrategyController.authPass → TAppUserSiteFavoriteClient),此轮询任务暂停(如需回退恢复 @Scheduled 即可)
    // @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);
    }
}