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 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 drops) { if (drops == null || drops.isEmpty() || !StringUtils.hasText(templateId)) { return; } List siteIds = drops.stream().map(SitePriceDropNotifyVO::getSiteId) .filter(Objects::nonNull).distinct().collect(Collectors.toList()); if (siteIds.isEmpty()) { return; } Map priceMap = drops.stream() .collect(Collectors.toMap(SitePriceDropNotifyVO::getSiteId, Function.identity(), (a, b) -> a)); List 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); } }