longz
2026-08-06 35d3dc45fbdc65eb23d5cc754134fbf240419f86
ruoyi-service/ruoyi-account/src/main/java/com/ruoyi/account/service/impl/TAppUserSiteFavoriteServiceImpl.java
@@ -1,20 +1,131 @@
package com.ruoyi.account.service.impl;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.account.api.model.TAppUser;
import com.ruoyi.account.api.model.TAppUserSiteFavorite;
import com.ruoyi.account.api.vo.SitePriceDropNotifyVO;
import com.ruoyi.account.mapper.TAppUserSiteFavoriteMapper;
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.common.core.utils.HttpUtils;
import com.ruoyi.common.redis.service.RedisService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Function;
import java.util.stream.Collectors;
@Slf4j
@Service
public class TAppUserSiteFavoriteServiceImpl
        extends ServiceImpl<TAppUserSiteFavoriteMapper, TAppUserSiteFavorite>
        implements TAppUserSiteFavoriteService {
    private static final String SEND_URL = "https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=";
    @Resource
    private TAppUserService appUserService;
    @Resource
    private RestTemplate wxRestTemplate;
    @Resource
    private WeixinProperties wxConfig;
    @Resource
    private RedisService redisService;
    @Value("${wx.applet.price-drop-template-id:7nCycRUZxQ2jxAb2UaYazjp2sPZy3qYyeLqVytyhHhY}")
    private String templateId;
    @Value("${wx.applet.price-drop-page:pagesMine/favoriteSite/favoriteSite}")
    private String page;
    @Override
    public void saveOrRestore(Long appUserId, Integer siteId, BigDecimal favoritePrice, Boolean notifyEnabled) {
        baseMapper.upsert(appUserId, siteId, favoritePrice, Boolean.TRUE.equals(notifyEnabled));
    }
    @Override
    public void notifyPriceDrop(List<SitePriceDropNotifyVO> drops) {
        if (drops == null || drops.isEmpty() || !StringUtils.hasText(templateId)) {
            return;
        }
        List<Integer> siteIds = drops.stream().map(SitePriceDropNotifyVO::getSiteId)
                .filter(Objects::nonNull).distinct().collect(Collectors.toList());
        if (siteIds.isEmpty()) {
            return;
        }
        Map<Integer, SitePriceDropNotifyVO> priceMap = drops.stream()
                .collect(Collectors.toMap(SitePriceDropNotifyVO::getSiteId, Function.identity(), (a, b) -> a));
        List<TAppUserSiteFavorite> favorites = lambdaQuery()
                .eq(TAppUserSiteFavorite::getNotifyEnabled, true)
                .in(TAppUserSiteFavorite::getSiteId, siteIds)
                .list();
        for (TAppUserSiteFavorite favorite : favorites) {
            SitePriceDropNotifyVO drop = priceMap.get(favorite.getSiteId());
            if (drop == null || drop.getPrice() == null) {
                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, drop)) {
                favorite.setNotifyEnabled(false);
                favorite.setLastNotifiedPrice(drop.getPrice());
                updateById(favorite);
                log.info("收藏站点降价提醒发送成功,userId={}, siteId={}, price={}",
                        favorite.getAppUserId(), favorite.getSiteId(), drop.getPrice());
            }
        }
    }
    private boolean sendSubscribeMessage(String openId, TAppUserSiteFavorite favorite, SitePriceDropNotifyVO drop) {
        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(drop.getSiteName(), 20)));
        data.put("amount4", value(formatAmount(drop.getPrice())));
        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);
    }
}