Merge branch 'master' into cc_20251029_smz
This commit is contained in:
@@ -283,4 +283,10 @@ public class RedisConstant {
|
|||||||
public static final String SUBMIT_BUILD_KEY = "submit_build_key_";
|
public static final String SUBMIT_BUILD_KEY = "submit_build_key_";
|
||||||
|
|
||||||
public static final String GET_AI_MODULE = "get_ai_module_";
|
public static final String GET_AI_MODULE = "get_ai_module_";
|
||||||
|
|
||||||
|
public static final String HUOMA_STORE_DEVICE_RESOURCE_KEY = "huoma_store_device_resource";
|
||||||
|
|
||||||
|
public static final String HUO_MA_STORE_ID = "huo_ma_store_id";
|
||||||
|
|
||||||
|
public static final String HUO_MA_TOKEN= "huo_ma_token:{0}";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -310,9 +310,11 @@ public enum ErrorCodeEnum {
|
|||||||
MESSAGE_NOT_HANDLED(1610008,"当前消息无需处理,请确认消息处理类型!",null),
|
MESSAGE_NOT_HANDLED(1610008,"当前消息无需处理,请确认消息处理类型!",null),
|
||||||
MESSAGE_PUBLISH(1610009,"您选择通知任务正在发布中,请稍后重试!",null),
|
MESSAGE_PUBLISH(1610009,"您选择通知任务正在发布中,请稍后重试!",null),
|
||||||
|
|
||||||
NOT_FLAGSHIP_STORE(16100005,"非直营店,无法跳过缴费阶段!",null),
|
NOT_FLAGSHIP_STORE(1610010,"非直营店,无法跳过缴费阶段!",null),
|
||||||
NOT_FLAGSHIP_STORE_NOT_EXIST(16100006,"当前阶段加盟类型不能变更!",null),
|
NOT_FLAGSHIP_STORE_NOT_EXIST(1610011,"当前阶段加盟类型不能变更!",null),
|
||||||
JOIN_MODE_NOT_ALLOW_OPERATE(16100007,"加盟部人员只能新建加盟店或联营店,请确认!",null),
|
JOIN_MODE_NOT_ALLOW_OPERATE(1610012,"加盟部人员只能新建加盟店或联营店,请确认!",null),
|
||||||
|
STORE_NOT_FIND(1610013,"门店不存在",null),
|
||||||
|
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,58 @@
|
|||||||
|
package com.cool.store.enums;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Author suzhuhong
|
||||||
|
* @Date 2025/11/5 16:03
|
||||||
|
* @Version 1.0
|
||||||
|
*/
|
||||||
|
public enum SpecialTagEnum {
|
||||||
|
|
||||||
|
ELECTRONIC_PRICE_LIST("电子价目牌"),
|
||||||
|
ACTIVITY_CAROUSEL("活动轮播"),
|
||||||
|
ACTIVITY_PACKAGE("活动套餐"),
|
||||||
|
PROMOTIONAL_VIDEO("宣传视频");
|
||||||
|
|
||||||
|
private final String tagName;
|
||||||
|
|
||||||
|
SpecialTagEnum(String tagName) {
|
||||||
|
this.tagName = tagName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTagName() {
|
||||||
|
return tagName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据标签名称获取枚举值
|
||||||
|
*/
|
||||||
|
public static SpecialTagEnum fromTagName(String tagName) {
|
||||||
|
for (SpecialTagEnum tag : values()) {
|
||||||
|
if (tag.getTagName().equals(tagName)) {
|
||||||
|
return tag;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取所有标签名称列表
|
||||||
|
*/
|
||||||
|
public static List<String> getAllTagNames() {
|
||||||
|
return Arrays.stream(values())
|
||||||
|
.map(SpecialTagEnum::getTagName)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取电子价目牌标签名称
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static List<String> getElectronicPriceTagName() {
|
||||||
|
return Arrays.asList(ELECTRONIC_PRICE_LIST.getTagName());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
package com.cool.store.enums;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Administrator on 2020/1/20.
|
||||||
|
*/
|
||||||
|
public enum StoreStatusEnum {
|
||||||
|
|
||||||
|
//营业
|
||||||
|
OPEN("open","在营"),
|
||||||
|
//闭店
|
||||||
|
CLOSED("closed","闭店解约"),
|
||||||
|
//未开业
|
||||||
|
NOT_OPEN("not_open","未开业"),
|
||||||
|
//迁址
|
||||||
|
CHANGE_ADDRESS("change_address","迁址"),
|
||||||
|
//退单
|
||||||
|
CHARGEBACK("chargeback","退单"),
|
||||||
|
//暂停营业
|
||||||
|
CLOSE_UP("close_up","暂停营业");
|
||||||
|
;
|
||||||
|
|
||||||
|
|
||||||
|
private final String value;
|
||||||
|
|
||||||
|
private final String name;
|
||||||
|
|
||||||
|
StoreStatusEnum(String value, String name) {
|
||||||
|
this.value = value;
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static StoreStatusEnum parse(String value) {
|
||||||
|
for (StoreStatusEnum storeStatusEnum : StoreStatusEnum.values()) {
|
||||||
|
if (storeStatusEnum.getValue().equals(value)) {
|
||||||
|
return storeStatusEnum;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getName(String value) {
|
||||||
|
for (StoreStatusEnum storeStatusEnum : StoreStatusEnum.values()) {
|
||||||
|
if (storeStatusEnum.getValue().equals(value)) {
|
||||||
|
return storeStatusEnum.name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getCode(String flag) {
|
||||||
|
switch (flag) {
|
||||||
|
case "营业":
|
||||||
|
case "在营":
|
||||||
|
return "open";
|
||||||
|
case "闭店":
|
||||||
|
case "闭店解约":
|
||||||
|
return "closed";
|
||||||
|
case "未开业":
|
||||||
|
return "not_open";
|
||||||
|
case "迁址":
|
||||||
|
return "change_address";
|
||||||
|
case "退单":
|
||||||
|
return "chargeback";
|
||||||
|
case "暂停营业":
|
||||||
|
return "close_up";
|
||||||
|
}
|
||||||
|
return "open";
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
package com.cool.store.enums.wechat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Author suzhuhong
|
||||||
|
* @Date 2025/10/16 15:19
|
||||||
|
* @Version 1.0
|
||||||
|
*/
|
||||||
|
public enum WechatTemplateDetailEnum {
|
||||||
|
|
||||||
|
CHARACTER_STRING2("编号","character_string2"),
|
||||||
|
THING10("项目名称","thing10"),
|
||||||
|
TIME14("完成时间","time14"),
|
||||||
|
THING25("客户名称","thing25"),
|
||||||
|
THING60("位置","thing60"),
|
||||||
|
|
||||||
|
|
||||||
|
THING6("工单标题","thing6"),
|
||||||
|
TIME33("创建时间","time33"),
|
||||||
|
CHARACTER_STRING14("工单编号","character_string14"),
|
||||||
|
|
||||||
|
|
||||||
|
;
|
||||||
|
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCode() {
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCode(String code) {
|
||||||
|
this.code = code;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
private String code;
|
||||||
|
|
||||||
|
WechatTemplateDetailEnum(String name, String code) {
|
||||||
|
this.name = name;
|
||||||
|
this.code = code;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
package com.cool.store.enums.wechat;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonValue;
|
||||||
|
|
||||||
|
import java.lang.reflect.Array;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static com.cool.store.enums.wechat.WechatTemplateDetailEnum.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Author suzhuhong
|
||||||
|
* @Date 2025/10/10 14:39
|
||||||
|
* @Version 1.0
|
||||||
|
*/
|
||||||
|
public enum WechatTemplateEnum {
|
||||||
|
|
||||||
|
QUESTION_NOTICE("QUESTION_NOTICE", "T3sp5gBItHKD8oCeEiQMjn7JXpngFiz3dDcaArk84xY", "收到工单通知",
|
||||||
|
Arrays.asList(CHARACTER_STRING2,THING10,TIME14,THING25,THING60)),
|
||||||
|
|
||||||
|
NEW_QUESTION_NOTICE("new_question_notice", "35rmoQ5wEHvUgCgSIJ2CpOb1DOJgWOiy8J7DXT_e4_Y", "新工单提醒",
|
||||||
|
Arrays.asList(THING6,TIME33,CHARACTER_STRING14)),
|
||||||
|
|
||||||
|
;
|
||||||
|
|
||||||
|
|
||||||
|
private final String code;
|
||||||
|
private final String templateId;
|
||||||
|
private final String title;
|
||||||
|
private final List<WechatTemplateDetailEnum> contentList;
|
||||||
|
|
||||||
|
WechatTemplateEnum(String code, String templateId, String title, List<WechatTemplateDetailEnum> contentList) {
|
||||||
|
this.code = code;
|
||||||
|
this.templateId = templateId;
|
||||||
|
this.title = title;
|
||||||
|
this.contentList = contentList;
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonValue
|
||||||
|
public String getCode() {
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTemplateId() {
|
||||||
|
return templateId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTitle() {
|
||||||
|
return title;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<WechatTemplateDetailEnum> getContentList() {
|
||||||
|
return contentList;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据code获取枚举
|
||||||
|
*/
|
||||||
|
public static WechatTemplateEnum getByCode(String code) {
|
||||||
|
for (WechatTemplateEnum template : values()) {
|
||||||
|
if (template.getCode().equals(code)) {
|
||||||
|
return template;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据模板ID获取枚举
|
||||||
|
*/
|
||||||
|
public static WechatTemplateEnum getByTemplateId(String templateId) {
|
||||||
|
for (WechatTemplateEnum template : values()) {
|
||||||
|
if (template.getTemplateId().equals(templateId)) {
|
||||||
|
return template;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
package com.cool.store.utils;
|
package com.cool.store.utils;
|
||||||
|
|
||||||
|
import cn.hutool.core.bean.copier.CopyOptions;
|
||||||
import com.github.pagehelper.PageInfo;
|
import com.github.pagehelper.PageInfo;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@@ -28,6 +29,18 @@ public class BeanUtil extends cn.hutool.core.bean.BeanUtil {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static <T, R> List<R> toList(List<T> list, Class<R> clazz, CopyOptions copyOptions) {
|
||||||
|
if (list == null || list.isEmpty()) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
List<R> result = new ArrayList<>(list.size());
|
||||||
|
for (T t : list) {
|
||||||
|
R r = toBean(t, clazz, copyOptions);
|
||||||
|
result.add(r);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
public static <T, R> PageInfo<R> toPage(PageInfo<T> page, Class<R> clazz) {
|
public static <T, R> PageInfo<R> toPage(PageInfo<T> page, Class<R> clazz) {
|
||||||
PageInfo<R> newPage = new PageInfo<>();
|
PageInfo<R> newPage = new PageInfo<>();
|
||||||
newPage.setPages(page.getPages());
|
newPage.setPages(page.getPages());
|
||||||
|
|||||||
@@ -0,0 +1,62 @@
|
|||||||
|
package com.cool.store.utils;
|
||||||
|
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Author suzhuhong
|
||||||
|
* @Date 2025/11/4 17:34
|
||||||
|
* @Version 1.0
|
||||||
|
*/
|
||||||
|
public class BrowserVersionUtils {
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检测是否为旧版Chrome浏览器(版本小于60)
|
||||||
|
* @param userAgent 浏览器User-Agent字符串
|
||||||
|
* @return true-是旧版Chrome,false-不是旧版Chrome
|
||||||
|
*/
|
||||||
|
public static boolean isOldChromeBrowser(String userAgent) {
|
||||||
|
if (userAgent == null || userAgent.isEmpty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查是否是Chrome浏览器
|
||||||
|
if (!userAgent.contains("Chrome")) {
|
||||||
|
return false; // 不是Chrome浏览器
|
||||||
|
}
|
||||||
|
|
||||||
|
// 提取Chrome版本号
|
||||||
|
Integer chromeVersion = extractChromeVersion(userAgent);
|
||||||
|
|
||||||
|
if (chromeVersion == null) {
|
||||||
|
return false; // 无法提取版本号
|
||||||
|
}
|
||||||
|
|
||||||
|
// 判断版本是否小于60
|
||||||
|
return chromeVersion < 60;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从User-Agent中提取Chrome主版本号
|
||||||
|
* @param userAgent 浏览器User-Agent字符串
|
||||||
|
* @return Chrome主版本号,如果无法提取返回null
|
||||||
|
*/
|
||||||
|
public static Integer extractChromeVersion(String userAgent) {
|
||||||
|
// 正则表达式匹配 Chrome/版本号 模式
|
||||||
|
Pattern pattern = Pattern.compile("Chrome/(\\d+)");
|
||||||
|
Matcher matcher = pattern.matcher(userAgent);
|
||||||
|
|
||||||
|
if (matcher.find()) {
|
||||||
|
try {
|
||||||
|
return Integer.parseInt(matcher.group(1));
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
System.err.println("版本号格式错误: " + matcher.group(1));
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,197 @@
|
|||||||
|
package com.cool.store.utils;
|
||||||
|
import com.cool.store.enums.ErrorCodeEnum;
|
||||||
|
import com.cool.store.exception.ServiceException;
|
||||||
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import okhttp3.*;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Author suzhuhong
|
||||||
|
* @Date 2025/10/10 14:21
|
||||||
|
* @Version 1.0
|
||||||
|
* OkHttp工具类
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Component
|
||||||
|
public class OkHttpUtil {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private OkHttpClient okHttpClient;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ObjectMapper objectMapper;
|
||||||
|
|
||||||
|
private static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GET请求
|
||||||
|
*/
|
||||||
|
public String doGet(String url) throws IOException {
|
||||||
|
return doGet(url, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GET请求 - 带请求头
|
||||||
|
*/
|
||||||
|
public String doGet(String url, Map<String, String> headers) throws IOException {
|
||||||
|
Request.Builder builder = new Request.Builder().url(url);
|
||||||
|
|
||||||
|
// 添加请求头
|
||||||
|
if (headers != null && !headers.isEmpty()) {
|
||||||
|
headers.forEach(builder::addHeader);
|
||||||
|
}
|
||||||
|
|
||||||
|
Request request = builder.build();
|
||||||
|
|
||||||
|
try (Response response = okHttpClient.newCall(request).execute()) {
|
||||||
|
if (!response.isSuccessful()) {
|
||||||
|
throw new IOException("Unexpected code: " + response);
|
||||||
|
}
|
||||||
|
ResponseBody body = response.body();
|
||||||
|
return body != null ? body.string() : null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* POST请求 - JSON数据
|
||||||
|
*/
|
||||||
|
public String doPostJson(String url, Object data) throws IOException {
|
||||||
|
return doPostJson(url, data, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* POST请求 - JSON数据,带请求头
|
||||||
|
*/
|
||||||
|
public String doPostJson(String url, Object data, Map<String, String> headers) throws IOException {
|
||||||
|
//打印日志
|
||||||
|
logRequest(url, data);
|
||||||
|
|
||||||
|
String json = objectMapper.writeValueAsString(data);
|
||||||
|
RequestBody requestBody = RequestBody.create( JSON,json);
|
||||||
|
Request.Builder builder = new Request.Builder()
|
||||||
|
.url(url)
|
||||||
|
.post(requestBody);
|
||||||
|
|
||||||
|
// 添加请求头
|
||||||
|
if (headers != null && !headers.isEmpty()) {
|
||||||
|
headers.forEach(builder::addHeader);
|
||||||
|
}
|
||||||
|
|
||||||
|
Request request = builder.build();
|
||||||
|
|
||||||
|
try (Response response = okHttpClient.newCall(request).execute()) {
|
||||||
|
if (!response.isSuccessful()) {
|
||||||
|
throw new ServiceException(ErrorCodeEnum.THIRD_API_ERROR,
|
||||||
|
"HTTP请求失败,状态码: " + response.code());
|
||||||
|
}
|
||||||
|
ResponseBody body = response.body();
|
||||||
|
|
||||||
|
String responseBody = body != null ? body.string() : null;
|
||||||
|
|
||||||
|
logResponse(url, response.code(), responseBody);
|
||||||
|
return responseBody;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 异步GET请求
|
||||||
|
*/
|
||||||
|
public void doGetAsync(String url, Callback callback) {
|
||||||
|
doGetAsync(url, null, callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 异步GET请求 - 带请求头
|
||||||
|
*/
|
||||||
|
public void doGetAsync(String url, Map<String, String> headers, Callback callback) {
|
||||||
|
Request.Builder builder = new Request.Builder().url(url);
|
||||||
|
|
||||||
|
if (headers != null && !headers.isEmpty()) {
|
||||||
|
headers.forEach(builder::addHeader);
|
||||||
|
}
|
||||||
|
|
||||||
|
Request request = builder.build();
|
||||||
|
okHttpClient.newCall(request).enqueue(callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 异步POST请求
|
||||||
|
*/
|
||||||
|
public void doPostAsync(String url, Object data, Callback callback) {
|
||||||
|
doPostAsync(url, data, null, callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 异步POST请求 - 带请求头
|
||||||
|
*/
|
||||||
|
public void doPostAsync(String url, Object data, Map<String, String> headers, Callback callback) {
|
||||||
|
try {
|
||||||
|
String json = objectMapper.writeValueAsString(data);
|
||||||
|
RequestBody requestBody = RequestBody.create( JSON,json);
|
||||||
|
|
||||||
|
Request.Builder builder = new Request.Builder()
|
||||||
|
.url(url)
|
||||||
|
.post(requestBody);
|
||||||
|
|
||||||
|
if (headers != null && !headers.isEmpty()) {
|
||||||
|
headers.forEach(builder::addHeader);
|
||||||
|
}
|
||||||
|
|
||||||
|
Request request = builder.build();
|
||||||
|
okHttpClient.newCall(request).enqueue(callback);
|
||||||
|
} catch (IOException e) {
|
||||||
|
callback.onFailure(null, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void logRequest(String url, Object requestBody) {
|
||||||
|
if (log.isInfoEnabled()) {
|
||||||
|
try {
|
||||||
|
log.info("\n======= 请求开始 =======\n" +
|
||||||
|
"API地址: {}\n" +
|
||||||
|
"请求参数: {}\n" +
|
||||||
|
"======= 请求结束 =======",
|
||||||
|
url,
|
||||||
|
objectMapper.writerWithDefaultPrettyPrinter()
|
||||||
|
.writeValueAsString(requestBody));
|
||||||
|
} catch (JsonProcessingException e) {
|
||||||
|
log.warn("日志JSON序列化失败", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void logResponse(String url, int statusCode, String responseBody) {
|
||||||
|
if (log.isInfoEnabled()) {
|
||||||
|
try {
|
||||||
|
// 尝试美化JSON输出
|
||||||
|
Object json = objectMapper.readValue(responseBody, Object.class);
|
||||||
|
String prettyResponse = objectMapper.writerWithDefaultPrettyPrinter()
|
||||||
|
.writeValueAsString(json);
|
||||||
|
|
||||||
|
log.info("\n======= 响应开始 =======\n" +
|
||||||
|
"API地址: {}\n" +
|
||||||
|
"HTTP状态码: {}\n" +
|
||||||
|
"响应内容: {}\n" +
|
||||||
|
"======= 响应结束 =======",
|
||||||
|
url,
|
||||||
|
statusCode,
|
||||||
|
prettyResponse);
|
||||||
|
} catch (Exception e) {
|
||||||
|
// 非JSON响应或解析失败时直接输出原始内容
|
||||||
|
log.info("\n======= 响应开始 =======\n" +
|
||||||
|
"API地址: {}\n" +
|
||||||
|
"HTTP状态码: {}\n" +
|
||||||
|
"原始响应: {}\n" +
|
||||||
|
"======= 响应结束 =======",
|
||||||
|
url,
|
||||||
|
statusCode,
|
||||||
|
responseBody);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
package com.cool.store.dao;
|
package com.cool.store.dao;
|
||||||
|
|
||||||
|
import com.cool.store.dto.wechat.ServiceAccountOpenIdDTO;
|
||||||
import com.cool.store.entity.HyPartnerUserInfoDO;
|
import com.cool.store.entity.HyPartnerUserInfoDO;
|
||||||
import com.cool.store.mapper.HyPartnerUserInfoMapper;
|
import com.cool.store.mapper.HyPartnerUserInfoMapper;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
@@ -112,4 +113,11 @@ public class HyPartnerUserInfoDAO {
|
|||||||
|
|
||||||
return hyPartnerUserInfoMapper.selectPasswordIsNull();
|
return hyPartnerUserInfoMapper.selectPasswordIsNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<ServiceAccountOpenIdDTO> selectLastBindRecord(List<String> mobileList){
|
||||||
|
if (CollectionUtils.isEmpty(mobileList)){
|
||||||
|
return Lists.newArrayList();
|
||||||
|
}
|
||||||
|
return hyPartnerUserInfoMapper.selectLastBindRecord(mobileList);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,4 +40,8 @@ public class OldShopDAO {
|
|||||||
List<OldShopDO> list = oldShopMapper.selectByExample(example);
|
List<OldShopDO> list = oldShopMapper.selectByExample(example);
|
||||||
return list.isEmpty() ? null : list.get(0);
|
return list.isEmpty() ? null : list.get(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void insertSelective(OldShopDO oldShopDO) {
|
||||||
|
oldShopMapper.insertSelective(oldShopDO);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,6 +31,27 @@ public class PartnerUserWechatBindDAO {
|
|||||||
return partnerUserWechatBindMapper.insert(partnerUserWechatBindDO);
|
return partnerUserWechatBindMapper.insert(partnerUserWechatBindDO);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新
|
||||||
|
* @param partnerUserWechatBindDO
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public Integer update(PartnerUserWechatBindDO partnerUserWechatBindDO) {
|
||||||
|
if (partnerUserWechatBindDO == null) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return partnerUserWechatBindMapper.update(partnerUserWechatBindDO);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新所有的unionId对应的服务号ID
|
||||||
|
* @param unionId 开发平台的用户ID
|
||||||
|
* @param serviceAccountOpenId 服务号ID
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public Integer updateByUnionId(String unionId,String serviceAccountOpenId) {
|
||||||
|
return partnerUserWechatBindMapper.updateByUnionId(unionId,serviceAccountOpenId);
|
||||||
|
}
|
||||||
|
|
||||||
public PartnerUserWechatBindDO getByOpenIdAndPartnerId(String partnerId, String openId) {
|
public PartnerUserWechatBindDO getByOpenIdAndPartnerId(String partnerId, String openId) {
|
||||||
if (StringUtil.isEmpty(partnerId)|| StringUtil.isEmpty(openId)){
|
if (StringUtil.isEmpty(partnerId)|| StringUtil.isEmpty(openId)){
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package com.cool.store.mapper;
|
package com.cool.store.mapper;
|
||||||
|
|
||||||
|
import com.cool.store.dto.wechat.ServiceAccountOpenIdDTO;
|
||||||
import com.cool.store.entity.HyPartnerUserInfoDO;
|
import com.cool.store.entity.HyPartnerUserInfoDO;
|
||||||
import org.apache.ibatis.annotations.Mapper;
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
import org.apache.ibatis.annotations.Param;
|
import org.apache.ibatis.annotations.Param;
|
||||||
@@ -55,4 +56,6 @@ public interface HyPartnerUserInfoMapper extends tk.mybatis.mapper.common.Mappe
|
|||||||
|
|
||||||
List<HyPartnerUserInfoDO> selectPasswordIsNull();
|
List<HyPartnerUserInfoDO> selectPasswordIsNull();
|
||||||
|
|
||||||
|
List<ServiceAccountOpenIdDTO> selectLastBindRecord(@Param("mobileList") List<String> mobileList);
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -18,6 +18,22 @@ public interface PartnerUserWechatBindMapper {
|
|||||||
*/
|
*/
|
||||||
Integer insert(PartnerUserWechatBindDO partnerUserWechatBindDO);
|
Integer insert(PartnerUserWechatBindDO partnerUserWechatBindDO);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新数据
|
||||||
|
* @param partnerUserWechatBindDO
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
Integer update(PartnerUserWechatBindDO partnerUserWechatBindDO);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新所有的unionId对应的服务号ID
|
||||||
|
* @param unionId 开发平台的用户ID
|
||||||
|
* @param serviceAccountOpenId 服务号ID
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
Integer updateByUnionId(String unionId,String serviceAccountOpenId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据partnerId与openId查询
|
* 根据partnerId与openId查询
|
||||||
* @param partnerId
|
* @param partnerId
|
||||||
|
|||||||
@@ -195,4 +195,23 @@
|
|||||||
</foreach>
|
</foreach>
|
||||||
</update>
|
</update>
|
||||||
|
|
||||||
|
<select id="selectLastBindRecord" resultType="com.cool.store.dto.wechat.ServiceAccountOpenIdDTO">
|
||||||
|
select
|
||||||
|
b.partner_id as partnerId,
|
||||||
|
b.union_id as unionId,
|
||||||
|
b.service_account_open_id as serviceAccountOpenId,
|
||||||
|
MAX(b.update_time) as lastUpdateTime
|
||||||
|
from xfsg_partner_user_info a
|
||||||
|
left join xfsg_partner_user_wechat_bind b
|
||||||
|
on a.partner_id = b.partner_id
|
||||||
|
where b.partner_id is not null
|
||||||
|
and service_account_open_id is not null
|
||||||
|
<if test="mobileList !=null and mobileList.size>0">
|
||||||
|
<foreach collection="mobileList" open="and mobile in (" close=")" separator="," item="mobile">
|
||||||
|
#{mobile}
|
||||||
|
</foreach>
|
||||||
|
</if>
|
||||||
|
GROUP BY b.partner_id
|
||||||
|
</select>
|
||||||
|
|
||||||
</mapper>
|
</mapper>
|
||||||
@@ -8,6 +8,8 @@
|
|||||||
<result column="open_id" property="openId" jdbcType="VARCHAR" />
|
<result column="open_id" property="openId" jdbcType="VARCHAR" />
|
||||||
<result column="bind_time" property="bindTime" jdbcType="TIMESTAMP" />
|
<result column="bind_time" property="bindTime" jdbcType="TIMESTAMP" />
|
||||||
<result column="partner_id" property="partnerId" jdbcType="VARCHAR" />
|
<result column="partner_id" property="partnerId" jdbcType="VARCHAR" />
|
||||||
|
<result column="union_id" property="unionId" jdbcType="VARCHAR" />
|
||||||
|
<result column="service_account_open_id" property="serviceAccountOpenId" jdbcType="VARCHAR" />
|
||||||
<result column="create_time" property="createTime" jdbcType="TIMESTAMP" />
|
<result column="create_time" property="createTime" jdbcType="TIMESTAMP" />
|
||||||
<result column="update_time" property="updateTime" jdbcType="TIMESTAMP" />
|
<result column="update_time" property="updateTime" jdbcType="TIMESTAMP" />
|
||||||
</resultMap>
|
</resultMap>
|
||||||
@@ -17,15 +19,33 @@
|
|||||||
open_id,
|
open_id,
|
||||||
bind_time,
|
bind_time,
|
||||||
partner_id,
|
partner_id,
|
||||||
|
union_id,
|
||||||
create_time
|
create_time
|
||||||
) VALUES (
|
) VALUES (
|
||||||
#{openId, jdbcType=VARCHAR},
|
#{openId, jdbcType=VARCHAR},
|
||||||
#{bindTime, jdbcType=TIMESTAMP},
|
#{bindTime, jdbcType=TIMESTAMP},
|
||||||
#{partnerId, jdbcType=VARCHAR},
|
#{partnerId, jdbcType=VARCHAR},
|
||||||
|
#{unionId, jdbcType=VARCHAR},
|
||||||
#{createTime, jdbcType=TIMESTAMP}
|
#{createTime, jdbcType=TIMESTAMP}
|
||||||
)
|
)
|
||||||
</insert>
|
</insert>
|
||||||
|
|
||||||
|
<update id="update" parameterType="com.cool.store.entity.PartnerUserWechatBindDO">
|
||||||
|
UPDATE xfsg_partner_user_wechat_bind
|
||||||
|
<set>
|
||||||
|
<if test="unionId != null">
|
||||||
|
union_id = #{unionId, jdbcType=VARCHAR},
|
||||||
|
</if>
|
||||||
|
</set>
|
||||||
|
where id = #{id}
|
||||||
|
</update>
|
||||||
|
|
||||||
|
<update id="updateByUnionId" >
|
||||||
|
UPDATE xfsg_partner_user_wechat_bind
|
||||||
|
set service_account_open_id = #{serviceAccountOpenId}
|
||||||
|
where union_id = #{unionId}
|
||||||
|
</update>
|
||||||
|
|
||||||
<select id="selectByPartnerAndOpenId" resultMap="BaseResultMap">
|
<select id="selectByPartnerAndOpenId" resultMap="BaseResultMap">
|
||||||
select * from xfsg_partner_user_wechat_bind where partner_id = #{partnerId} and open_id = #{openId}
|
select * from xfsg_partner_user_wechat_bind where partner_id = #{partnerId} and open_id = #{openId}
|
||||||
</select>
|
</select>
|
||||||
|
|||||||
@@ -56,4 +56,7 @@ public class StoreDTO {
|
|||||||
private String managerSupervisionName;
|
private String managerSupervisionName;
|
||||||
@ApiModelProperty("所属大区/分部")
|
@ApiModelProperty("所属大区/分部")
|
||||||
private String branchName;
|
private String branchName;
|
||||||
|
|
||||||
|
@ApiModelProperty("门店状态")
|
||||||
|
private String status;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
package com.cool.store.dto.huoma;
|
||||||
|
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Author suzhuhong
|
||||||
|
* @Date 2025/11/6 11:09
|
||||||
|
* @Version 1.0
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class AccountTagDTO {
|
||||||
|
|
||||||
|
@ApiModelProperty("门店编码")
|
||||||
|
private String storeNum;
|
||||||
|
|
||||||
|
@ApiModelProperty("设备名称")
|
||||||
|
private String deviceName;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
package com.cool.store.dto.huoma;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 火码账号DTO
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author wangff
|
||||||
|
* @since 2025/9/23
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class HuoMaAccountDTO {
|
||||||
|
/**
|
||||||
|
* 账号
|
||||||
|
*/
|
||||||
|
private String account;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 密码
|
||||||
|
*/
|
||||||
|
private String password;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否已查询
|
||||||
|
*/
|
||||||
|
private Boolean isQuery;
|
||||||
|
|
||||||
|
public HuoMaAccountDTO(String account, String password) {
|
||||||
|
this.account = account;
|
||||||
|
this.password = password;
|
||||||
|
this.isQuery = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
package com.cool.store.dto.huoma;
|
||||||
|
|
||||||
|
import io.swagger.annotations.Api;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotEmpty;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Author suzhuhong
|
||||||
|
* @Date 2025/11/5 14:43
|
||||||
|
* @Version 1.0
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class ProgramReqDTO {
|
||||||
|
|
||||||
|
@ApiModelProperty(name = "门店编码",required = true)
|
||||||
|
private String storeCode;
|
||||||
|
|
||||||
|
@ApiModelProperty(name = "设备名称",required = true)
|
||||||
|
@NotEmpty(message = "设备名称不能为空")
|
||||||
|
private String deviceName;
|
||||||
|
|
||||||
|
@ApiModelProperty(name = "第几页,",required = true)
|
||||||
|
private Integer index;
|
||||||
|
|
||||||
|
@ApiModelProperty(name ="每页数量",required = true)
|
||||||
|
private Integer size;
|
||||||
|
|
||||||
|
@ApiModelProperty(name = "时间",hidden = true)
|
||||||
|
private String date;
|
||||||
|
|
||||||
|
@ApiModelProperty(name = "排序",hidden = true)
|
||||||
|
private String sort;
|
||||||
|
|
||||||
|
@ApiModelProperty("标签id列表")
|
||||||
|
private List<Integer> tagIds;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
package com.cool.store.dto.huoma;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Author suzhuhong
|
||||||
|
* @Date 2025/11/5 14:44
|
||||||
|
* @Version 1.0
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
|
public class ProgramResponseDTO {
|
||||||
|
|
||||||
|
@ApiModelProperty("节目ID")
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@ApiModelProperty("节目名称")
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@ApiModelProperty("节目缩略图")
|
||||||
|
private String thumbnail;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
package com.cool.store.dto.huoma;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.annotation.JSONField;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotEmpty;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Author suzhuhong
|
||||||
|
* @Date 2025/11/5 17:06
|
||||||
|
* @Version 1.0
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class PublishDTO {
|
||||||
|
|
||||||
|
@ApiModelProperty(name = "门店编号",required = true)
|
||||||
|
@NotEmpty(message = "门店编码不能为空")
|
||||||
|
private String storeCode;
|
||||||
|
@ApiModelProperty(name = "设备ID列表",required = true)
|
||||||
|
@NotEmpty(message = "设备ID列表不能为空")
|
||||||
|
@JSONField(name = "terminals")
|
||||||
|
private List<String> deviceIdList;
|
||||||
|
@ApiModelProperty("节目id")
|
||||||
|
private Long programId;
|
||||||
|
}
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
package com.cool.store.dto.huoma;
|
||||||
|
|
||||||
|
import com.cool.store.utils.BrowserVersionUtils;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Author: WangShuo
|
||||||
|
* @Date: 2025/08/13/16:24
|
||||||
|
* @Version 1.0
|
||||||
|
* @注释:
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class StoreEquipmentDTO {
|
||||||
|
/**
|
||||||
|
* 已授权登录数
|
||||||
|
*/
|
||||||
|
private Integer activeCount;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 总设备
|
||||||
|
*/
|
||||||
|
private Integer terminalCount;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 网点ID
|
||||||
|
*/
|
||||||
|
private Integer pointId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 网点号
|
||||||
|
*/
|
||||||
|
private String pointCode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 签到数
|
||||||
|
*/
|
||||||
|
private Integer signCount;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 在线
|
||||||
|
*/
|
||||||
|
|
||||||
|
private Integer connectCount;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
StoreEquipmentDTO that = (StoreEquipmentDTO) o;
|
||||||
|
return Objects.equals(pointCode, that.pointCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hashCode(pointCode);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
package com.cool.store.dto.huoma;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Author suzhuhong
|
||||||
|
* @Date 2025/8/18 16:00
|
||||||
|
* @Version 1.0
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class StoreRequestDTO {
|
||||||
|
|
||||||
|
private String reportCode;
|
||||||
|
|
||||||
|
private Integer index;
|
||||||
|
|
||||||
|
private Integer size;
|
||||||
|
|
||||||
|
private Params params;
|
||||||
|
|
||||||
|
public StoreRequestDTO(String reportCode, Integer index, Integer size, String shopCode) {
|
||||||
|
this.reportCode = reportCode;
|
||||||
|
this.index = index;
|
||||||
|
this.size = size;
|
||||||
|
this.params = new Params(shopCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
static class Params{
|
||||||
|
private String inputText_2;
|
||||||
|
|
||||||
|
public Params(String inputText_2) {
|
||||||
|
this.inputText_2 = inputText_2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
package com.cool.store.dto.huoma;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Author suzhuhong
|
||||||
|
* @Date 2025/8/18 16:38
|
||||||
|
* @Version 1.0
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class StoreXinFaDetailRequestDTO {
|
||||||
|
|
||||||
|
private Integer index;
|
||||||
|
|
||||||
|
private Integer size;
|
||||||
|
|
||||||
|
private Integer pointId;
|
||||||
|
|
||||||
|
public StoreXinFaDetailRequestDTO(Integer index, Integer size, Integer pointId) {
|
||||||
|
this.index = index;
|
||||||
|
this.size = size;
|
||||||
|
this.pointId = pointId;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,81 @@
|
|||||||
|
package com.cool.store.dto.huoma;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.parser.DefaultJSONParser;
|
||||||
|
import com.alibaba.fastjson.parser.deserializer.ObjectDeserializer;
|
||||||
|
import com.cool.store.utils.BrowserVersionUtils;
|
||||||
|
import com.cool.store.utils.StringUtil;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.lang.reflect.Type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Author suzhuhong
|
||||||
|
* @Date 2025/8/18 16:27
|
||||||
|
* @Version 1.0
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
|
public class StoreXinFaDeviceDetail {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设备ID
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "设备ID")
|
||||||
|
private String id;
|
||||||
|
|
||||||
|
@ApiModelProperty("设备id")
|
||||||
|
private String deviceId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设备名称
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "设备名称")
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设备连接状态 0:未连接 1:已连接
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "设备连接状态 false:未连接 true:已连接")
|
||||||
|
private Boolean isConnect;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设备总内存
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "设备总内存")
|
||||||
|
private String totalRam;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设备可用内存
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "设备可用内存")
|
||||||
|
private String availRam;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设备浏览器信息
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "设备浏览器信息")
|
||||||
|
private String userAgent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 内用内存小于300M 或者 浏览器版本小于60
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "内用内存小于300M 或者 浏览器版本小于60")
|
||||||
|
private Boolean flag;
|
||||||
|
|
||||||
|
public boolean getFlag() {
|
||||||
|
if (StringUtil.isEmpty(availRam)||StringUtil.isEmpty(userAgent)){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
Boolean isOldChromeBrowser = BrowserVersionUtils.isOldChromeBrowser(userAgent);
|
||||||
|
long availableMemoryMB = Long.parseLong(availRam) / (1024 * 1024);
|
||||||
|
return availableMemoryMB < 300 || isOldChromeBrowser;
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
package com.cool.store.dto.huoma;
|
||||||
|
|
||||||
|
import io.swagger.models.auth.In;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Author suzhuhong
|
||||||
|
* @Date 2025/11/5 9:33
|
||||||
|
* @Version 1.0
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class TagDTO {
|
||||||
|
|
||||||
|
private String channelType;
|
||||||
|
|
||||||
|
private Integer index;
|
||||||
|
|
||||||
|
private Integer size;
|
||||||
|
|
||||||
|
private String type;
|
||||||
|
|
||||||
|
public TagDTO(String channelType, Integer index, Integer size, String type) {
|
||||||
|
this.channelType = channelType;
|
||||||
|
this.index = index;
|
||||||
|
this.size = size;
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
package com.cool.store.dto.huoma;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Author suzhuhong
|
||||||
|
* @Date 2025/11/5 9:41
|
||||||
|
* @Version 1.0
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
|
public class TagDetailDTO {
|
||||||
|
|
||||||
|
@ApiModelProperty("标签Id")
|
||||||
|
private Integer id;
|
||||||
|
|
||||||
|
@ApiModelProperty("标签名称")
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
package com.cool.store.dto.recipe;
|
||||||
|
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 服务包菜品数据
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author wangff
|
||||||
|
* @since 2025/10/30
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class LaunchDataDTO {
|
||||||
|
@ApiModelProperty("名称")
|
||||||
|
private String spName;
|
||||||
|
|
||||||
|
@ApiModelProperty("上新时间,yyyy-MM-dd")
|
||||||
|
private String upSaleDate;
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
package com.cool.store.dto.recipe;
|
||||||
|
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 菜品上新DTO
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author wangff
|
||||||
|
* @since 2025/11/3
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class RecipeLaunchDTO {
|
||||||
|
@ApiModelProperty("商品编码")
|
||||||
|
private String goodsCode;
|
||||||
|
|
||||||
|
@ApiModelProperty("商品图片")
|
||||||
|
private String goodsImageUrl;
|
||||||
|
|
||||||
|
@ApiModelProperty("商品名称")
|
||||||
|
private String goodsName;
|
||||||
|
|
||||||
|
@ApiModelProperty("上新时间")
|
||||||
|
private String launchTime;
|
||||||
|
|
||||||
|
@ApiModelProperty("单日最高销量")
|
||||||
|
private Integer maxQty;
|
||||||
|
|
||||||
|
@ApiModelProperty("销量总计")
|
||||||
|
private Integer sumQty;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
package com.cool.store.dto.recipe;
|
||||||
|
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 服务包菜品上新DTO
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author wangff
|
||||||
|
* @since 2025/11/3
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class RecipeSpLaunchDTO {
|
||||||
|
@ApiModelProperty("菜品上新记录")
|
||||||
|
private List<RecipeLaunchDTO> recipeRecordList;
|
||||||
|
|
||||||
|
@ApiModelProperty("服务包执行记录")
|
||||||
|
private List<ServicePackageExecuteDTO> spRecordList;
|
||||||
|
}
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
package com.cool.store.dto.recipe;
|
||||||
|
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 营收数据
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author wangff
|
||||||
|
* @since 2025/10/30
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class RevenueDataDTO {
|
||||||
|
@ApiModelProperty("门店编码")
|
||||||
|
private String storeCode;
|
||||||
|
|
||||||
|
@ApiModelProperty("营业额")
|
||||||
|
private BigDecimal amt;
|
||||||
|
|
||||||
|
@ApiModelProperty("实收")
|
||||||
|
private BigDecimal receivedAmt;
|
||||||
|
|
||||||
|
@ApiModelProperty("营业时间,yyyy-MM-dd")
|
||||||
|
private String businessDate;
|
||||||
|
|
||||||
|
@ApiModelProperty("服务包列表")
|
||||||
|
private List<LaunchDataDTO> otherLaunchDates;
|
||||||
|
|
||||||
|
@ApiModelProperty("菜品列表")
|
||||||
|
private List<LaunchDataDTO> otherRecipeLaunchDates;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
package com.cool.store.dto.recipe;
|
||||||
|
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 营收数据查询DTO
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author wangff
|
||||||
|
* @since 2025/10/30
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class RevenueDataQueryDTO {
|
||||||
|
@ApiModelProperty("门店编码")
|
||||||
|
private String storeCode;
|
||||||
|
|
||||||
|
@ApiModelProperty("业务时间开始")
|
||||||
|
private String businessDateFrom;
|
||||||
|
|
||||||
|
@ApiModelProperty("业务时间结束")
|
||||||
|
private String businessDateTo;
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
package com.cool.store.dto.recipe;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||||
|
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 服务包执行DTO
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author wangff
|
||||||
|
* @since 2025/11/3
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class ServicePackageExecuteDTO {
|
||||||
|
@ApiModelProperty("服务包执行时间")
|
||||||
|
private String executeTime;
|
||||||
|
|
||||||
|
@ApiModelProperty("服务包图片")
|
||||||
|
private String spImage;
|
||||||
|
|
||||||
|
@ApiModelProperty("服务包名称")
|
||||||
|
private String spName;
|
||||||
|
|
||||||
|
@ApiModelProperty("服务包id")
|
||||||
|
@JsonSerialize(using = ToStringSerializer.class)
|
||||||
|
private Long spId;
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package com.cool.store.dto.wechat;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Author suzhuhong
|
||||||
|
* @Date 2025/10/10 15:01
|
||||||
|
* @Version 1.0
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class AccessTokenDTO {
|
||||||
|
|
||||||
|
private String access_token;
|
||||||
|
|
||||||
|
private Integer expires_in;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
package com.cool.store.dto.wechat;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Author suzhuhong
|
||||||
|
* @Date 2025/10/14 14:39
|
||||||
|
* @Version 1.0
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class CallbackMessageDTO {
|
||||||
|
|
||||||
|
private String toUserName;
|
||||||
|
|
||||||
|
private String fromUserName;
|
||||||
|
|
||||||
|
private Long createTime;
|
||||||
|
|
||||||
|
private String msgType;
|
||||||
|
|
||||||
|
private String event;
|
||||||
|
|
||||||
|
private String eventKey;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
package com.cool.store.dto.wechat;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Author suzhuhong
|
||||||
|
* @Date 2025/10/16 14:13
|
||||||
|
* @Version 1.0
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class ServiceAccountOpenIdDTO {
|
||||||
|
|
||||||
|
private String partnerId;
|
||||||
|
|
||||||
|
private String unionId;
|
||||||
|
|
||||||
|
private String serviceAccountOpenId;
|
||||||
|
|
||||||
|
private Date lastUpdateTime;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,90 @@
|
|||||||
|
package com.cool.store.dto.wechat;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Author suzhuhong
|
||||||
|
* @Date 2025/10/10 14:36
|
||||||
|
* @Version 1.0
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class WechatTemplateMessageDTO {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 接收者openid
|
||||||
|
*/
|
||||||
|
@JsonProperty("touser")
|
||||||
|
private String toUser;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 模板ID
|
||||||
|
*/
|
||||||
|
@JsonProperty("template_id")
|
||||||
|
private String templateId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 模板跳转链接(非必须)
|
||||||
|
*/
|
||||||
|
private String url;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 跳小程序所需数据,不需跳小程序可不用传该数据
|
||||||
|
*/
|
||||||
|
private MiniprogramDTO miniprogram;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 模板数据
|
||||||
|
*/
|
||||||
|
private Map<String, TemplateDataItemDTO> data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 小程序跳转DTO
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public static class MiniprogramDTO {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 所需跳转到的小程序appid
|
||||||
|
*/
|
||||||
|
private String appid;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 所需跳转到小程序的具体页面路径,支持带参数
|
||||||
|
*/
|
||||||
|
private String pagepath;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 模板数据项DTO
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public static class TemplateDataItemDTO {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 模板内容
|
||||||
|
*/
|
||||||
|
private String value;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 模板内容字体颜色,不填默认为黑色
|
||||||
|
*/
|
||||||
|
private String color;
|
||||||
|
|
||||||
|
public TemplateDataItemDTO() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public TemplateDataItemDTO(String value) {
|
||||||
|
this.value = value;
|
||||||
|
this.color = "#333333";
|
||||||
|
}
|
||||||
|
|
||||||
|
public TemplateDataItemDTO(String value, String color) {
|
||||||
|
this.value = value;
|
||||||
|
this.color = color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,115 @@
|
|||||||
|
package com.cool.store.dto.wechat;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Author suzhuhong
|
||||||
|
* @Date 2025/10/15 9:56
|
||||||
|
* @Version 1.0
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class WechatUserInfoDTO {
|
||||||
|
/**
|
||||||
|
* 用户是否订阅该公众号标识
|
||||||
|
* 0代表未关注,1代表关注
|
||||||
|
*/
|
||||||
|
private Integer subscribe;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户的标识,对当前公众号唯一
|
||||||
|
*/
|
||||||
|
private String openid;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户的昵称
|
||||||
|
*/
|
||||||
|
private String nickname;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户的性别
|
||||||
|
* 1为男性,2为女性,0为未知
|
||||||
|
*/
|
||||||
|
private Integer sex;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户所在城市
|
||||||
|
*/
|
||||||
|
private String city;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户所在国家
|
||||||
|
*/
|
||||||
|
private String country;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户所在省份
|
||||||
|
*/
|
||||||
|
private String province;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户的语言
|
||||||
|
* 简体中文为zh_CN
|
||||||
|
*/
|
||||||
|
private String language;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户头像
|
||||||
|
*/
|
||||||
|
private String headimgurl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户关注时间,为时间戳
|
||||||
|
*/
|
||||||
|
@JsonProperty("subscribe_time")
|
||||||
|
private Long subscribeTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 只有在用户将公众号绑定到微信开放平台帐号后,才会出现该字段
|
||||||
|
*/
|
||||||
|
private String unionid;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 公众号运营者对粉丝的备注
|
||||||
|
*/
|
||||||
|
private String remark;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户所在的分组ID(兼容旧的用户分组接口)
|
||||||
|
*/
|
||||||
|
private Integer groupid;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户被打上的标签ID列表
|
||||||
|
*/
|
||||||
|
@JsonProperty("tagid_list")
|
||||||
|
private List<Integer> tagidList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回用户关注的渠道来源
|
||||||
|
*/
|
||||||
|
@JsonProperty("subscribe_scene")
|
||||||
|
private String subscribeScene;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 二维码扫码场景(开发者自定义)
|
||||||
|
*/
|
||||||
|
@JsonProperty("qr_scene")
|
||||||
|
private Long qrScene;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 二维码扫码场景描述(开发者自定义)
|
||||||
|
*/
|
||||||
|
@JsonProperty("qr_scene_str")
|
||||||
|
private String qrSceneStr;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否已关注
|
||||||
|
*/
|
||||||
|
public boolean isSubscribed() {
|
||||||
|
return subscribe != null && subscribe == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,13 +1,19 @@
|
|||||||
package com.cool.store.entity;
|
package com.cool.store.entity;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
import javax.persistence.*;
|
import javax.persistence.*;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
@Table(name = "xfsg_old_shop")
|
@Table(name = "xfsg_old_shop")
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
@Builder
|
||||||
public class OldShopDO {
|
public class OldShopDO {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -36,6 +36,10 @@ public class PartnerUserWechatBindDO implements Serializable {
|
|||||||
*/
|
*/
|
||||||
private String partnerId;
|
private String partnerId;
|
||||||
|
|
||||||
|
private String unionId;
|
||||||
|
|
||||||
|
private String serviceAccountOpenId;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建时间
|
* 创建时间
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -0,0 +1,29 @@
|
|||||||
|
package com.cool.store.request.recipe;
|
||||||
|
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotBlank;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 营收数据Request
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author wangff
|
||||||
|
* @since 2025/10/30
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class RevenueDataRequest {
|
||||||
|
@ApiModelProperty("门店id")
|
||||||
|
@NotBlank(message = "门店id不能为空")
|
||||||
|
private String storeId;
|
||||||
|
|
||||||
|
@ApiModelProperty("业务时间开始,yyyy-MM-dd")
|
||||||
|
@NotBlank(message = "业务时间开始不能为空")
|
||||||
|
private String businessDateFrom;
|
||||||
|
|
||||||
|
@ApiModelProperty("业务时间结束,yyyy-MM-dd")
|
||||||
|
@NotBlank(message = "业务时间结束不能为空")
|
||||||
|
private String businessDateTo;
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
package com.cool.store.vo.recipe;
|
||||||
|
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 服务包菜品数据
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author wangff
|
||||||
|
* @since 2025/10/30
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class LaunchDataVO {
|
||||||
|
@ApiModelProperty("名称")
|
||||||
|
private String spName;
|
||||||
|
|
||||||
|
@ApiModelProperty("上新时间,yyyy-MM-dd")
|
||||||
|
private String upSaleDate;
|
||||||
|
}
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
package com.cool.store.vo.recipe;
|
||||||
|
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 营收数据VO
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author wangff
|
||||||
|
* @since 2025/10/30
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class RevenueDataVO {
|
||||||
|
@ApiModelProperty("门店编码")
|
||||||
|
private String storeNum;
|
||||||
|
|
||||||
|
@ApiModelProperty("营业额")
|
||||||
|
private BigDecimal amt;
|
||||||
|
|
||||||
|
@ApiModelProperty("实收")
|
||||||
|
private BigDecimal receivedAmt;
|
||||||
|
|
||||||
|
@ApiModelProperty("营业时间,yyyy-MM-dd")
|
||||||
|
private String businessDate;
|
||||||
|
|
||||||
|
@ApiModelProperty("服务包列表")
|
||||||
|
private List<LaunchDataVO> otherLaunchDates;
|
||||||
|
|
||||||
|
@ApiModelProperty("菜品列表")
|
||||||
|
private List<LaunchDataVO> otherRecipeLaunchDates;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,126 @@
|
|||||||
|
package com.cool.store.builder;
|
||||||
|
|
||||||
|
import com.cool.store.config.weixin.WechatMiniappProperties;
|
||||||
|
import com.cool.store.dto.wechat.WechatTemplateMessageDTO;
|
||||||
|
import com.cool.store.enums.wechat.WechatTemplateEnum;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Author suzhuhong
|
||||||
|
* @Date 2025/10/10 14:34
|
||||||
|
* @Version 1.0
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class TemplateMessageBuilder {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private WechatMiniappProperties wechatMiniappProperties;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构建普通模板消息
|
||||||
|
*/
|
||||||
|
public WechatTemplateMessageDTO buildNormalTemplate(String openId,
|
||||||
|
WechatTemplateEnum template,
|
||||||
|
Map<String, Object> data) {
|
||||||
|
WechatTemplateMessageDTO messageDTO = new WechatTemplateMessageDTO();
|
||||||
|
messageDTO.setToUser(openId);
|
||||||
|
messageDTO.setTemplateId(template.getTemplateId());
|
||||||
|
|
||||||
|
// 设置URL(如果data中包含url)
|
||||||
|
if (data.containsKey("url")) {
|
||||||
|
messageDTO.setUrl((String) data.get("url"));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 构建模板数据
|
||||||
|
messageDTO.setData(buildTemplateData(data));
|
||||||
|
|
||||||
|
return messageDTO;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构建小程序跳转模板消息
|
||||||
|
*/
|
||||||
|
public WechatTemplateMessageDTO buildMiniappTemplate(String openId,
|
||||||
|
WechatTemplateEnum template,
|
||||||
|
Map<String, Object> data,
|
||||||
|
String miniAppPagePath) {
|
||||||
|
WechatTemplateMessageDTO messageDTO = new WechatTemplateMessageDTO();
|
||||||
|
messageDTO.setToUser(openId);
|
||||||
|
messageDTO.setTemplateId(template.getTemplateId());
|
||||||
|
|
||||||
|
// 设置小程序跳转
|
||||||
|
WechatTemplateMessageDTO.MiniprogramDTO miniProgram = new WechatTemplateMessageDTO.MiniprogramDTO();
|
||||||
|
miniProgram.setAppid(wechatMiniappProperties.getAppId());
|
||||||
|
miniProgram.setPagepath(miniAppPagePath != null ? miniAppPagePath : wechatMiniappProperties.getDefaultPagePath());
|
||||||
|
messageDTO.setMiniprogram(miniProgram);
|
||||||
|
|
||||||
|
// 设置备用URL(如果data中包含url)
|
||||||
|
if (data.containsKey("url")) {
|
||||||
|
messageDTO.setUrl((String) data.get("url"));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 构建模板数据
|
||||||
|
messageDTO.setData(buildTemplateData(data));
|
||||||
|
|
||||||
|
return messageDTO;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构建小程序跳转模板消息(带备用URL)
|
||||||
|
*/
|
||||||
|
public WechatTemplateMessageDTO buildMiniAppTemplateWithUrl(String openId,
|
||||||
|
WechatTemplateEnum template,
|
||||||
|
Map<String, Object> data,
|
||||||
|
String miniAppPagePath,
|
||||||
|
String backupUrl) {
|
||||||
|
WechatTemplateMessageDTO messageDTO = buildMiniappTemplate(openId, template, data, miniAppPagePath);
|
||||||
|
|
||||||
|
// 设置备用URL
|
||||||
|
if (backupUrl != null && !backupUrl.trim().isEmpty()) {
|
||||||
|
messageDTO.setUrl(backupUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
return messageDTO;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构建模板数据
|
||||||
|
*/
|
||||||
|
private Map<String, WechatTemplateMessageDTO.TemplateDataItemDTO> buildTemplateData(Map<String, Object> data) {
|
||||||
|
Map<String, WechatTemplateMessageDTO.TemplateDataItemDTO> templateData = new HashMap<>();
|
||||||
|
|
||||||
|
data.forEach((key, value) -> {
|
||||||
|
if (!"url".equals(key) && value != null) {
|
||||||
|
WechatTemplateMessageDTO.TemplateDataItemDTO item =
|
||||||
|
new WechatTemplateMessageDTO.TemplateDataItemDTO(
|
||||||
|
value.toString(),
|
||||||
|
getColorByField(key)
|
||||||
|
);
|
||||||
|
templateData.put(key, item);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return templateData;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据字段名获取颜色
|
||||||
|
*/
|
||||||
|
private String getColorByField(String fieldName) {
|
||||||
|
switch (fieldName) {
|
||||||
|
case "amount":
|
||||||
|
case "refundAmount":
|
||||||
|
case "couponValue":
|
||||||
|
case "character_string2":
|
||||||
|
return "#FF0000"; // 金额类字段用红色
|
||||||
|
case "orderNo":
|
||||||
|
case "expressNo":
|
||||||
|
return "#173177"; // 编号类字段用蓝色
|
||||||
|
default:
|
||||||
|
return "#333333"; // 默认用深灰色
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
package com.cool.store.config.weixin;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Author suzhuhong
|
||||||
|
* @Date 2025/10/10 14:41
|
||||||
|
* @Version 1.0
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Configuration
|
||||||
|
@ConfigurationProperties(prefix = "wechat.miniapp")
|
||||||
|
public class WechatMiniappProperties {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 小程序appId
|
||||||
|
*/
|
||||||
|
private String appId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 小程序页面路径
|
||||||
|
*/
|
||||||
|
private String defaultPagePath ;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否使用小程序跳转
|
||||||
|
*/
|
||||||
|
private boolean enabled = false;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
package com.cool.store.config.weixin;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Author suzhuhong
|
||||||
|
* @Date 2025/10/10 14:29
|
||||||
|
* @Version 1.0
|
||||||
|
* 微信服务号配置
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Configuration
|
||||||
|
@ConfigurationProperties(prefix = "wechat.mp")
|
||||||
|
public class WechatMpProperties {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 公众号appId
|
||||||
|
*/
|
||||||
|
private String appId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 公众号appSecret
|
||||||
|
*/
|
||||||
|
private String appSecret;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取access_token的URL
|
||||||
|
*/
|
||||||
|
private String accessTokenUrl = "https://api.weixin.qq.com/cgi-bin/token";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送模板消息的URL
|
||||||
|
*/
|
||||||
|
private String sendTemplateMessageUrl = "https://api.weixin.qq.com/cgi-bin/message/template/send";
|
||||||
|
}
|
||||||
@@ -0,0 +1,157 @@
|
|||||||
|
package com.cool.store.handler;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSONObject;
|
||||||
|
import com.cool.store.dao.PartnerUserWechatBindDAO;
|
||||||
|
import com.cool.store.dto.wechat.WechatUserInfoDTO;
|
||||||
|
import com.cool.store.service.wechat.WechatTemplateService;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.w3c.dom.Document;
|
||||||
|
import org.w3c.dom.Node;
|
||||||
|
import org.w3c.dom.NodeList;
|
||||||
|
import org.xml.sax.InputSource;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import javax.xml.parsers.DocumentBuilder;
|
||||||
|
import javax.xml.parsers.DocumentBuilderFactory;
|
||||||
|
import java.io.StringReader;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Author suzhuhong
|
||||||
|
* @Date 2025/10/14 14:56
|
||||||
|
* @Version 1.0
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
@Slf4j
|
||||||
|
public class WeChatHandler {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
PartnerUserWechatBindDAO partnerUserWechatBindDAO;
|
||||||
|
@Resource
|
||||||
|
WechatTemplateService wechatTemplateService;
|
||||||
|
|
||||||
|
public Map<String, Object> parseXmlToMap(String xmlContent) throws Exception {
|
||||||
|
Map<String, Object> result = new HashMap<>();
|
||||||
|
|
||||||
|
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
|
||||||
|
factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
|
||||||
|
|
||||||
|
DocumentBuilder builder = factory.newDocumentBuilder();
|
||||||
|
Document document = builder.parse(new InputSource(new StringReader(xmlContent)));
|
||||||
|
|
||||||
|
NodeList nodes = document.getDocumentElement().getChildNodes();
|
||||||
|
for (int i = 0; i < nodes.getLength(); i++) {
|
||||||
|
Node node = nodes.item(i);
|
||||||
|
if (node.getNodeType() == Node.ELEMENT_NODE) {
|
||||||
|
String tagName = node.getNodeName();
|
||||||
|
String textContent = node.getTextContent();
|
||||||
|
result.put(tagName, textContent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public String processMessage(Map<String, Object> messageMap) {
|
||||||
|
String msgType = (String) messageMap.get("MsgType");
|
||||||
|
String event = (String) messageMap.get("Event");
|
||||||
|
|
||||||
|
switch (msgType) {
|
||||||
|
case "event":
|
||||||
|
return handleEvent(messageMap);
|
||||||
|
|
||||||
|
// case "text":
|
||||||
|
// return handleTextMessage(message);
|
||||||
|
//
|
||||||
|
// case "image":
|
||||||
|
// return handleImageMessage(message);
|
||||||
|
|
||||||
|
default:
|
||||||
|
// 其他类型的消息直接回复success
|
||||||
|
return "success";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String handleEvent(Map<String, Object> messageMap) {
|
||||||
|
String event = (String) messageMap.get("Event");
|
||||||
|
String fromUserName = (String) messageMap.get("FromUserName");
|
||||||
|
String toUserName = (String) messageMap.get("ToUserName");
|
||||||
|
|
||||||
|
switch (event) {
|
||||||
|
case "subscribe":
|
||||||
|
// 关注事件 - 绑定用户
|
||||||
|
return handleSubscribeEvent(fromUserName,toUserName);
|
||||||
|
|
||||||
|
case "unsubscribe":
|
||||||
|
// 取消关注事件 - 解绑用户
|
||||||
|
return handleUnsubscribeEvent(fromUserName,toUserName);
|
||||||
|
|
||||||
|
default:
|
||||||
|
return buildWelcomeReply(fromUserName, toUserName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String handleSubscribeEvent(String fromUserName,String toUserName) {
|
||||||
|
try {
|
||||||
|
|
||||||
|
//根据openId 获取用户信息
|
||||||
|
WechatUserInfoDTO userInfo = wechatTemplateService.getUserInfo(fromUserName, null);
|
||||||
|
|
||||||
|
log.info("handleSubscribeEvent: {}", JSONObject.toJSONString(userInfo));
|
||||||
|
|
||||||
|
//根据unionId 更新服务号ID
|
||||||
|
if (userInfo != null) {
|
||||||
|
partnerUserWechatBindDAO.updateByUnionId(userInfo.getUnionid(),fromUserName);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 立即回复欢迎消息
|
||||||
|
return buildWelcomeReply(fromUserName, toUserName);
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
// 即使处理失败也要返回success
|
||||||
|
return buildWelcomeReply(fromUserName, toUserName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理取消关注事件
|
||||||
|
*/
|
||||||
|
private String handleUnsubscribeEvent(String fromUserName,String toUserName) {
|
||||||
|
|
||||||
|
// 异步处理用户解绑
|
||||||
|
//userBindingService.unbindOfficialAccountUser(openId);
|
||||||
|
|
||||||
|
return "success";
|
||||||
|
}
|
||||||
|
|
||||||
|
private String buildSuccessReply(String fromUser, String toUser) {
|
||||||
|
return String.format(
|
||||||
|
"<xml>" +
|
||||||
|
"<ToUserName><![CDATA[%s]]></ToUserName>" +
|
||||||
|
"<FromUserName><![CDATA[%s]]></FromUserName>" +
|
||||||
|
"<CreateTime>%d</CreateTime>" +
|
||||||
|
"<MsgType><![CDATA[text]]></MsgType>" +
|
||||||
|
"<Content><![CDATA[success]]></Content>" +
|
||||||
|
"</xml>",
|
||||||
|
fromUser, toUser, System.currentTimeMillis() / 1000
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private String buildWelcomeReply(String fromUser, String toUser) {
|
||||||
|
return String.format(
|
||||||
|
"<xml>" +
|
||||||
|
"<ToUserName><![CDATA[%s]]></ToUserName>" +
|
||||||
|
"<FromUserName><![CDATA[%s]]></FromUserName>" +
|
||||||
|
"<CreateTime>%d</CreateTime>" +
|
||||||
|
"<MsgType><![CDATA[text]]></MsgType>" +
|
||||||
|
"<Content><![CDATA[欢迎关注!您已成功绑定通知服务,可以接收小程序的重要消息通知。]]></Content>" +
|
||||||
|
"</xml>",
|
||||||
|
fromUser, toUser, System.currentTimeMillis() / 1000
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,10 +1,11 @@
|
|||||||
package com.cool.store.service;
|
package com.cool.store.service;
|
||||||
|
|
||||||
import com.cool.store.dto.FoodTokenDTO;
|
import com.cool.store.dto.FoodTokenDTO;
|
||||||
import com.cool.store.dto.GetAccessTokenDTO;
|
import com.cool.store.dto.recipe.RecipeSpLaunchDTO;
|
||||||
import com.cool.store.dto.store.StoreUserPositionDTO;
|
|
||||||
import com.cool.store.dto.store.StoreUserUpdateDTO;
|
import com.cool.store.dto.store.StoreUserUpdateDTO;
|
||||||
|
import com.cool.store.request.recipe.RevenueDataRequest;
|
||||||
import com.cool.store.response.caipin.StoreUserResponse;
|
import com.cool.store.response.caipin.StoreUserResponse;
|
||||||
|
import com.cool.store.vo.recipe.RevenueDataVO;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@@ -31,4 +32,17 @@ public interface ThirdFoodService {
|
|||||||
*/
|
*/
|
||||||
StoreUserResponse pushStoreUser(List<StoreUserUpdateDTO> storeUserUpdateDTOList);
|
StoreUserResponse pushStoreUser(List<StoreUserUpdateDTO> storeUserUpdateDTOList);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询门店营收实收数据
|
||||||
|
* @param request 营收数据Request
|
||||||
|
* @return 营收数据VO列表
|
||||||
|
*/
|
||||||
|
List<RevenueDataVO> getRevenueData(RevenueDataRequest request);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询菜品服务包上新数据
|
||||||
|
* @param request 请求request
|
||||||
|
* @return 服务包菜品上新DTO
|
||||||
|
*/
|
||||||
|
RecipeSpLaunchDTO getRecipeServiceLaunch(RevenueDataRequest request);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,9 +9,12 @@ import com.cool.store.dto.notice.MessageTemplateCountDTO;
|
|||||||
import com.cool.store.dto.notice.NoticeDTO;
|
import com.cool.store.dto.notice.NoticeDTO;
|
||||||
import com.cool.store.dto.store.AuthStoreUserDTO;
|
import com.cool.store.dto.store.AuthStoreUserDTO;
|
||||||
import com.cool.store.dto.store.StoreAreaDTO;
|
import com.cool.store.dto.store.StoreAreaDTO;
|
||||||
|
import com.cool.store.dto.wechat.ServiceAccountOpenIdDTO;
|
||||||
import com.cool.store.entity.*;
|
import com.cool.store.entity.*;
|
||||||
import com.cool.store.enums.ErrorCodeEnum;
|
import com.cool.store.enums.ErrorCodeEnum;
|
||||||
import com.cool.store.enums.notice.*;
|
import com.cool.store.enums.notice.*;
|
||||||
|
import com.cool.store.enums.wechat.WechatTemplateDetailEnum;
|
||||||
|
import com.cool.store.enums.wechat.WechatTemplateEnum;
|
||||||
import com.cool.store.exception.ServiceException;
|
import com.cool.store.exception.ServiceException;
|
||||||
import com.cool.store.mapper.StoreGroupMappingMapper;
|
import com.cool.store.mapper.StoreGroupMappingMapper;
|
||||||
import com.cool.store.mapper.StoreMapper;
|
import com.cool.store.mapper.StoreMapper;
|
||||||
@@ -19,12 +22,16 @@ import com.cool.store.request.notice.*;
|
|||||||
import com.cool.store.response.bigdata.ApiResponse;
|
import com.cool.store.response.bigdata.ApiResponse;
|
||||||
import com.cool.store.service.MessageTemplateService;
|
import com.cool.store.service.MessageTemplateService;
|
||||||
import com.cool.store.service.StoreService;
|
import com.cool.store.service.StoreService;
|
||||||
|
import com.cool.store.service.wechat.WechatTemplateService;
|
||||||
import com.cool.store.utils.CoolDateUtils;
|
import com.cool.store.utils.CoolDateUtils;
|
||||||
import com.cool.store.utils.RedisUtilPool;
|
import com.cool.store.utils.RedisUtilPool;
|
||||||
|
import com.cool.store.utils.poi.DateUtils;
|
||||||
import com.cool.store.vo.PartnerUserInfoVO;
|
import com.cool.store.vo.PartnerUserInfoVO;
|
||||||
import com.cool.store.vo.notice.*;
|
import com.cool.store.vo.notice.*;
|
||||||
import com.github.pagehelper.PageHelper;
|
import com.github.pagehelper.PageHelper;
|
||||||
import com.github.pagehelper.PageInfo;
|
import com.github.pagehelper.PageInfo;
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.commons.collections4.CollectionUtils;
|
import org.apache.commons.collections4.CollectionUtils;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
@@ -67,10 +74,14 @@ public class MessageTemplateServiceImpl implements MessageTemplateService {
|
|||||||
@Resource
|
@Resource
|
||||||
MatterConfigDAO matterConfigDAO;
|
MatterConfigDAO matterConfigDAO;
|
||||||
@Resource
|
@Resource
|
||||||
|
WechatTemplateService wechatTemplateService;
|
||||||
|
@Resource
|
||||||
RedisUtilPool redisUtilPool;
|
RedisUtilPool redisUtilPool;
|
||||||
@Resource
|
@Resource
|
||||||
TaskExecutor noticeThreadPool;
|
TaskExecutor noticeThreadPool;
|
||||||
@Resource
|
@Resource
|
||||||
|
HyPartnerUserInfoDAO hyPartnerUserInfoDAO;
|
||||||
|
@Resource
|
||||||
MessageIssueService messageIssueService;
|
MessageIssueService messageIssueService;
|
||||||
|
|
||||||
|
|
||||||
@@ -210,10 +221,38 @@ public class MessageTemplateServiceImpl implements MessageTemplateService {
|
|||||||
JSONObject.toJSONString(request.getStoreInfoList()),
|
JSONObject.toJSONString(request.getStoreInfoList()),
|
||||||
JSONObject.toJSONString(request.getUserInfoList()),
|
JSONObject.toJSONString(request.getUserInfoList()),
|
||||||
userId);
|
userId);
|
||||||
|
|
||||||
|
//发送通知
|
||||||
|
Set<String> userIds = authUser.values().stream().flatMap(Collection::stream).collect(Collectors.toSet());
|
||||||
|
|
||||||
|
//分批 查询用户信息
|
||||||
|
List<String> openIdList = new ArrayList<>();
|
||||||
|
Lists.partition(new ArrayList<>(userIds), 100).forEach(x->{
|
||||||
|
List<EnterpriseUserDO> userInfoByUserIds = enterpriseUserDAO.getUserInfoByUserIds(x);
|
||||||
|
//取出用户的手机号,过滤掉空的手机号
|
||||||
|
List<String> mobileList = userInfoByUserIds.stream().filter(user -> StringUtils.isNotBlank(user.getMobile())).map(EnterpriseUserDO::getMobile).collect(Collectors.toList());
|
||||||
|
if (CollectionUtils.isNotEmpty(mobileList)){
|
||||||
|
List<ServiceAccountOpenIdDTO> serviceAccountOpenIdDTOS = hyPartnerUserInfoDAO.selectLastBindRecord(mobileList);
|
||||||
|
if (CollectionUtils.isNotEmpty(serviceAccountOpenIdDTOS)){
|
||||||
|
//服务号ID
|
||||||
|
openIdList.addAll(serviceAccountOpenIdDTOS.stream().map(ServiceAccountOpenIdDTO::getServiceAccountOpenId).collect(Collectors.toList()));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
MessageTemplateDO messageTemplateDO = list.get(0);
|
||||||
|
Map<String, Object> data = new HashMap<>();
|
||||||
|
data.put(WechatTemplateDetailEnum.THING6.getCode(), messageTemplateDO.getMessageTitle());
|
||||||
|
data.put(WechatTemplateDetailEnum.TIME33.getCode(), DateUtils.parseDateToStr(DateUtils.SPECIAL_DATE_START, new Date()));
|
||||||
|
data.put(WechatTemplateDetailEnum.CHARACTER_STRING14.getCode(), messageTemplateDO.getMessageCode());
|
||||||
|
openIdList.forEach(x->{
|
||||||
|
wechatTemplateService.sendMiniAppTemplate(x, WechatTemplateEnum.NEW_QUESTION_NOTICE,data,"pages/notification/index");
|
||||||
|
});
|
||||||
// 即时消息下发
|
// 即时消息下发
|
||||||
messageIssueService.issueMessage(realtimeMessageList);
|
messageIssueService.issueMessage(realtimeMessageList);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.info("发布流程异常,已取消发布");
|
log.info("发布流程异常 e:{}",e.getMessage());
|
||||||
} finally {
|
} finally {
|
||||||
releaseLocks(lockKeys);
|
releaseLocks(lockKeys);
|
||||||
log.info("发布流程结束,已释放Redis锁");
|
log.info("发布流程结束,已释放Redis锁");
|
||||||
|
|||||||
@@ -59,6 +59,8 @@ public class ShopAccountServiceImpl implements ShopAccountService {
|
|||||||
ThirdXinGuanJiaService thirdXinGuanJiaService;
|
ThirdXinGuanJiaService thirdXinGuanJiaService;
|
||||||
@Resource
|
@Resource
|
||||||
private LineInfoDAO lineInfoDAO;
|
private LineInfoDAO lineInfoDAO;
|
||||||
|
@Resource
|
||||||
|
private StoreDao storeDao;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<ShopAccountDTO> getShopAccountByShopId(Long shopId) {
|
public List<ShopAccountDTO> getShopAccountByShopId(Long shopId) {
|
||||||
@@ -311,7 +313,17 @@ public class ShopAccountServiceImpl implements ShopAccountService {
|
|||||||
//查询老店关联表数据
|
//查询老店关联表数据
|
||||||
OldShopDO oldShopDO = oldShopDAO.getByCode(shopCode);
|
OldShopDO oldShopDO = oldShopDAO.getByCode(shopCode);
|
||||||
if (Objects.isNull(oldShopDO)) {
|
if (Objects.isNull(oldShopDO)) {
|
||||||
throw new ServiceException(ErrorCodeEnum.GET_YLS_CODE_FAIL);
|
StoreDO storeDO = storeDao.getByStoreNum(shopCode);
|
||||||
|
if (Objects.isNull(storeDO)) {
|
||||||
|
throw new ServiceException(ErrorCodeEnum.GET_YLS_CODE_FAIL);
|
||||||
|
}
|
||||||
|
oldShopDO = OldShopDO.builder()
|
||||||
|
.shopCode(shopCode)
|
||||||
|
.shopName(storeDO.getStoreName())
|
||||||
|
.mobile(storeDO.getTelephone())
|
||||||
|
.ylsShopCode("ZXA8_" + shopCode)
|
||||||
|
.build();
|
||||||
|
oldShopDAO.insertSelective(oldShopDO);
|
||||||
}
|
}
|
||||||
return oldShopDO.getYlsShopCode();
|
return oldShopDO.getYlsShopCode();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -399,6 +399,7 @@ public class StoreServiceImpl implements StoreService {
|
|||||||
dto.setJoinMode(JoinModeEnum.getByCode(store.getJoinModel()));
|
dto.setJoinMode(JoinModeEnum.getByCode(store.getJoinModel()));
|
||||||
dto.setBrand(FranchiseBrandEnum.getDescByCode(store.getJoinBrand()));
|
dto.setBrand(FranchiseBrandEnum.getDescByCode(store.getJoinBrand()));
|
||||||
dto.setOrderMiniProgramName(store.getMiniProgramOrderStoreName());
|
dto.setOrderMiniProgramName(store.getMiniProgramOrderStoreName());
|
||||||
|
dto.setStatus(StoreStatusEnum.getName(store.getStoreStatus()));
|
||||||
if (store.getRegionId() != null){
|
if (store.getRegionId() != null){
|
||||||
dto.setManagerSupervisionName(regionMap.get(store.getRegionId()));
|
dto.setManagerSupervisionName(regionMap.get(store.getRegionId()));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,17 +1,23 @@
|
|||||||
package com.cool.store.service.impl;
|
package com.cool.store.service.impl;
|
||||||
|
|
||||||
|
import cn.hutool.core.bean.copier.CopyOptions;
|
||||||
import cn.hutool.core.util.RandomUtil;
|
import cn.hutool.core.util.RandomUtil;
|
||||||
import com.alibaba.fastjson.JSONObject;
|
import com.cool.store.dao.StoreDao;
|
||||||
import com.cool.store.dto.FoodTokenDTO;
|
import com.cool.store.dto.FoodTokenDTO;
|
||||||
import com.cool.store.dto.GetAccessTokenDTO;
|
import com.cool.store.dto.recipe.RecipeSpLaunchDTO;
|
||||||
import com.cool.store.dto.store.StoreUserPositionDTO;
|
import com.cool.store.dto.recipe.RevenueDataDTO;
|
||||||
|
import com.cool.store.dto.recipe.RevenueDataQueryDTO;
|
||||||
import com.cool.store.dto.store.StoreUserUpdateDTO;
|
import com.cool.store.dto.store.StoreUserUpdateDTO;
|
||||||
|
import com.cool.store.entity.StoreDO;
|
||||||
import com.cool.store.enums.ErrorCodeEnum;
|
import com.cool.store.enums.ErrorCodeEnum;
|
||||||
import com.cool.store.exception.ServiceException;
|
import com.cool.store.exception.ServiceException;
|
||||||
|
import com.cool.store.request.recipe.RevenueDataRequest;
|
||||||
import com.cool.store.response.caipin.StoreUserResponse;
|
import com.cool.store.response.caipin.StoreUserResponse;
|
||||||
import com.cool.store.response.oppty.OpportunityApiResponse;
|
import com.cool.store.response.oppty.OpportunityApiResponse;
|
||||||
import com.cool.store.service.ThirdFoodService;
|
import com.cool.store.service.ThirdFoodService;
|
||||||
|
import com.cool.store.utils.BeanUtil;
|
||||||
import com.cool.store.utils.SignatureUtils;
|
import com.cool.store.utils.SignatureUtils;
|
||||||
|
import com.cool.store.vo.recipe.RevenueDataVO;
|
||||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
import com.fasterxml.jackson.databind.JavaType;
|
import com.fasterxml.jackson.databind.JavaType;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
@@ -24,9 +30,9 @@ import org.springframework.beans.factory.annotation.Value;
|
|||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import java.net.URI;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Objects;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Author suzhuhong
|
* @Author suzhuhong
|
||||||
@@ -45,6 +51,8 @@ public class ThirdFoodServiceImpl implements ThirdFoodService {
|
|||||||
OkHttpClient okHttpClient;
|
OkHttpClient okHttpClient;
|
||||||
@Resource
|
@Resource
|
||||||
ObjectMapper objectMapper;
|
ObjectMapper objectMapper;
|
||||||
|
@Resource
|
||||||
|
private StoreDao storeDao;
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -60,6 +68,29 @@ public class ThirdFoodServiceImpl implements ThirdFoodService {
|
|||||||
return executeApiCall(url, dto, StoreUserResponse.class);
|
return executeApiCall(url, dto, StoreUserResponse.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<RevenueDataVO> getRevenueData(RevenueDataRequest request) {
|
||||||
|
StoreDO storeDO = storeDao.getByStoreId(request.getStoreId());
|
||||||
|
if (Objects.isNull(storeDO)) {
|
||||||
|
throw new ServiceException(ErrorCodeEnum.STORE_NOT_FIND);
|
||||||
|
}
|
||||||
|
RevenueDataQueryDTO queryDTO = new RevenueDataQueryDTO(storeDO.getStoreNum(), request.getBusinessDateFrom(), request.getBusinessDateTo());
|
||||||
|
String url = "/v1/store/business";
|
||||||
|
List<RevenueDataDTO> list = executeApiCall(url, queryDTO, List.class);
|
||||||
|
return BeanUtil.toList(list, RevenueDataVO.class, CopyOptions.create().setFieldMapping(Collections.singletonMap("storeCode", "storeNum")));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RecipeSpLaunchDTO getRecipeServiceLaunch(RevenueDataRequest request) {
|
||||||
|
StoreDO storeDO = storeDao.getByStoreId(request.getStoreId());
|
||||||
|
if (Objects.isNull(storeDO)) {
|
||||||
|
throw new ServiceException(ErrorCodeEnum.STORE_NOT_FIND);
|
||||||
|
}
|
||||||
|
RevenueDataQueryDTO queryDTO = new RevenueDataQueryDTO(storeDO.getStoreNum(), request.getBusinessDateFrom(), request.getBusinessDateTo());
|
||||||
|
String url = "/v1/store/business/spRecipeList";
|
||||||
|
return executeApiCall(url, queryDTO, RecipeSpLaunchDTO.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private <T> T executeApiCall(String url, Object requestBody, Class<T> responseType) {
|
private <T> T executeApiCall(String url, Object requestBody, Class<T> responseType) {
|
||||||
// 1. 打印请求前日志
|
// 1. 打印请求前日志
|
||||||
|
|||||||
@@ -111,9 +111,16 @@ public class WechatMiniAppServiceImpl implements WechatMiniAppService {
|
|||||||
PartnerUserWechatBindDO bindDO = new PartnerUserWechatBindDO();
|
PartnerUserWechatBindDO bindDO = new PartnerUserWechatBindDO();
|
||||||
bindDO.setBindTime(new Date());
|
bindDO.setBindTime(new Date());
|
||||||
bindDO.setOpenId(openid);
|
bindDO.setOpenId(openid);
|
||||||
|
bindDO.setUnionId(unionId);
|
||||||
bindDO.setPartnerId(hyPartnerUserInfoDO.getPartnerId());
|
bindDO.setPartnerId(hyPartnerUserInfoDO.getPartnerId());
|
||||||
bindDO.setCreateTime(new Date());
|
bindDO.setCreateTime(new Date());
|
||||||
partnerUserWechatBindDAO.insertSelective(bindDO);
|
partnerUserWechatBindDAO.insertSelective(bindDO);
|
||||||
|
}else {
|
||||||
|
//维护unionId 针对老数据没有unionId
|
||||||
|
if (zlPartnerUserBindDO.getUnionId()==null){
|
||||||
|
zlPartnerUserBindDO.setUnionId(unionId);
|
||||||
|
partnerUserWechatBindDAO.update(zlPartnerUserBindDO);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
BeanUtil.copyProperties(hyPartnerUserInfoDO, userInfoVO);
|
BeanUtil.copyProperties(hyPartnerUserInfoDO, userInfoVO);
|
||||||
fillLineInfo(userInfoVO, hyPartnerUserInfoDO.getPartnerId());
|
fillLineInfo(userInfoVO, hyPartnerUserInfoDO.getPartnerId());
|
||||||
|
|||||||
@@ -0,0 +1,67 @@
|
|||||||
|
package com.cool.store.service.impl.xinfa;
|
||||||
|
|
||||||
|
import com.cool.store.dto.huoma.*;
|
||||||
|
import com.cool.store.enums.SpecialTagEnum;
|
||||||
|
import com.cool.store.response.ResponseResult;
|
||||||
|
import com.cool.store.service.xinfa.XinFaBusinessService;
|
||||||
|
import com.cool.store.service.xinfa.XinFaDeviceService;
|
||||||
|
import org.apache.commons.collections4.CollectionUtils;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Author suzhuhong
|
||||||
|
* @Date 2025/11/5 16:17
|
||||||
|
* @Version 1.0
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
public class XinFaBusinessServiceImpl implements XinFaBusinessService {
|
||||||
|
@Resource
|
||||||
|
XinFaDeviceService xinFaDeviceService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<StoreXinFaDeviceDetail> getStoreXinFaDeviceDetail(String storeNum) {
|
||||||
|
return xinFaDeviceService.getStoreXinFaDeviceDetail(storeNum);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<TagDetailDTO> getAccountAllTags(String storeNum,String deviceName) {
|
||||||
|
//如果是广告机,不需要展示标签
|
||||||
|
if (deviceName.contains("广告机")){
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
|
List<TagDetailDTO> accountAllTags = xinFaDeviceService.getAccountAllTags(storeNum);
|
||||||
|
if (accountAllTags != null){
|
||||||
|
return accountAllTags.stream()
|
||||||
|
.filter(tag -> tag.getName() != null &&
|
||||||
|
SpecialTagEnum.getAllTagNames().contains(tag.getName()))
|
||||||
|
.sorted(Comparator.comparing(tag -> SpecialTagEnum.getAllTagNames().indexOf(tag.getName())))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<ProgramResponseDTO> getProgramList(ProgramReqDTO programReqDTO) {
|
||||||
|
//如果没传tag 查所有 根据更新时间倒序排
|
||||||
|
programReqDTO.setSort("desc");
|
||||||
|
programReqDTO.setDate("updateTime");
|
||||||
|
if (CollectionUtils.isEmpty(programReqDTO.getTagIds())){
|
||||||
|
//设备名称包含 广告机 只查询电子价目表
|
||||||
|
programReqDTO.setTagIds(xinFaDeviceService.getAccountSpecialTagIds(programReqDTO.getStoreCode(), SpecialTagEnum.getElectronicPriceTagName()));
|
||||||
|
}
|
||||||
|
List<ProgramResponseDTO> programList = xinFaDeviceService.getProgramList(programReqDTO);
|
||||||
|
return programList;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Boolean publishProgram(PublishDTO publishDTO) {
|
||||||
|
return xinFaDeviceService.publish(publishDTO);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,149 @@
|
|||||||
|
package com.cool.store.service.wechat;
|
||||||
|
|
||||||
|
import com.cool.store.builder.TemplateMessageBuilder;
|
||||||
|
import com.cool.store.config.weixin.WechatMpProperties;
|
||||||
|
import com.cool.store.dto.wechat.AccessTokenDTO;
|
||||||
|
import com.cool.store.dto.wechat.WechatTemplateMessageDTO;
|
||||||
|
import com.cool.store.dto.wechat.WechatUserInfoDTO;
|
||||||
|
import com.cool.store.enums.wechat.WechatTemplateEnum;
|
||||||
|
import com.cool.store.utils.OkHttpUtil;
|
||||||
|
import com.cool.store.utils.RedisUtilPool;
|
||||||
|
import com.cool.store.utils.poi.StringUtils;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Author suzhuhong
|
||||||
|
* @Date 2025/10/10 14:15
|
||||||
|
* @Version 1.0
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Service
|
||||||
|
public class WechatTemplateService {
|
||||||
|
|
||||||
|
|
||||||
|
private static final String ACCESS_TOKEN_KEY = "wechat_service_account_access_token";
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private WechatMpProperties wechatMpProperties;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private TemplateMessageBuilder templateMessageBuilder;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private OkHttpUtil okHttpUtil;
|
||||||
|
@Autowired
|
||||||
|
private ObjectMapper objectMapper;
|
||||||
|
@Resource
|
||||||
|
private RedisUtilPool redisUtilPool;
|
||||||
|
|
||||||
|
|
||||||
|
public String getAccessToken() {
|
||||||
|
String cachedToken = redisUtilPool.getString(ACCESS_TOKEN_KEY);
|
||||||
|
if (StringUtils.isNotEmpty(cachedToken)) {
|
||||||
|
log.info("从 Redis 获取 access_token: {}", cachedToken);
|
||||||
|
return cachedToken;
|
||||||
|
}
|
||||||
|
String url = String.format("%s?grant_type=client_credential&appid=%s&secret=%s",
|
||||||
|
wechatMpProperties.getAccessTokenUrl(),
|
||||||
|
wechatMpProperties.getAppId(),
|
||||||
|
wechatMpProperties.getAppSecret());
|
||||||
|
try {
|
||||||
|
String result = okHttpUtil.doGet(url);
|
||||||
|
log.info("获取access_token响应: {}", result);
|
||||||
|
|
||||||
|
if (StringUtils.isNotEmpty( result)){
|
||||||
|
AccessTokenDTO responseDTO = objectMapper.readValue(result, AccessTokenDTO.class);
|
||||||
|
String accessToken = responseDTO.getAccess_token();
|
||||||
|
|
||||||
|
// 将获取到的 token 存入 Redis,设置过期时间(微信 token 有效期 7200 秒,这里设置 7000 秒)
|
||||||
|
if (StringUtils.isNotEmpty(accessToken)) {
|
||||||
|
redisUtilPool.setString(ACCESS_TOKEN_KEY, accessToken, 7000);
|
||||||
|
log.info("将 access_token 存入 Redis: {}", accessToken);
|
||||||
|
}
|
||||||
|
return accessToken;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
} catch (IOException e) {
|
||||||
|
log.error("获取access_token失败", e);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("解析access_token响应失败", e);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public WechatUserInfoDTO getUserInfo(String openId, String lang) {
|
||||||
|
String accessToken = getAccessToken();
|
||||||
|
//默认中国
|
||||||
|
lang = StringUtils.isEmpty(lang)?"zh_CN":lang;
|
||||||
|
if (accessToken == null) {
|
||||||
|
log.error("获取access_token失败");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
String url = String.format("https://api.weixin.qq.com/cgi-bin/user/info?access_token=%s&openid=%s",
|
||||||
|
accessToken, openId);
|
||||||
|
|
||||||
|
if (lang != null && !lang.trim().isEmpty()) {
|
||||||
|
url += "&lang=" + lang;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
String result = okHttpUtil.doGet(url);
|
||||||
|
log.debug("获取用户信息响应: {}", result);
|
||||||
|
WechatUserInfoDTO userInfo = objectMapper.readValue(result, WechatUserInfoDTO.class);
|
||||||
|
return userInfo;
|
||||||
|
} catch (IOException e) {
|
||||||
|
log.error("获取用户信息失败", e);
|
||||||
|
return null;
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("解析用户信息响应失败", e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean sendNormalTemplate(String openId, WechatTemplateEnum template, Map<String, Object> data) {
|
||||||
|
WechatTemplateMessageDTO messageDTO = templateMessageBuilder.buildNormalTemplate(openId, template, data);
|
||||||
|
return sendTemplateMessage(messageDTO);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean sendMiniAppTemplate(String openId, WechatTemplateEnum template,
|
||||||
|
Map<String, Object> data, String miniAppPagePath) {
|
||||||
|
WechatTemplateMessageDTO messageDTO = templateMessageBuilder.buildMiniappTemplate(
|
||||||
|
openId, template, data, miniAppPagePath);
|
||||||
|
return sendTemplateMessage(messageDTO);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean sendMiniAppTemplateWithUrl(String openId, WechatTemplateEnum template,
|
||||||
|
Map<String, Object> data, String miniAppPagePath, String backupUrl) {
|
||||||
|
WechatTemplateMessageDTO messageDTO = templateMessageBuilder.buildMiniAppTemplateWithUrl(
|
||||||
|
openId, template, data, miniAppPagePath, backupUrl);
|
||||||
|
return sendTemplateMessage(messageDTO);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean sendTemplateMessage(WechatTemplateMessageDTO messageDTO) {
|
||||||
|
String accessToken = getAccessToken();
|
||||||
|
if (accessToken == null) {
|
||||||
|
log.error("获取access_token失败,无法发送模板消息");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
String url = String.format("%s?access_token=%s",
|
||||||
|
wechatMpProperties.getSendTemplateMessageUrl(), accessToken);
|
||||||
|
|
||||||
|
log.info("发送模板消息: {}", messageDTO);
|
||||||
|
try {
|
||||||
|
String result = okHttpUtil.doPostJson(url, messageDTO);
|
||||||
|
log.info("发送模板消息响应: {}", result);
|
||||||
|
|
||||||
|
return Boolean.TRUE;
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("解析模板消息响应失败", e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
package com.cool.store.service.xinfa;
|
||||||
|
|
||||||
|
import com.cool.store.dto.huoma.*;
|
||||||
|
import com.cool.store.response.ResponseResult;
|
||||||
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Author suzhuhong
|
||||||
|
* @Date 2025/11/5 16:15
|
||||||
|
* @Version 1.0
|
||||||
|
*/
|
||||||
|
public interface XinFaBusinessService {
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取门店信发设备列表
|
||||||
|
* @param storeNum
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
List<StoreXinFaDeviceDetail> getStoreXinFaDeviceDetail(String storeNum);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取账号下有哪些标签
|
||||||
|
* @param storeNum
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
List<TagDetailDTO> getAccountAllTags(String storeNum,String deviceName);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取账号下有哪些节目、
|
||||||
|
* 通过门店在哪个账号下 确定账号
|
||||||
|
* @param programReqDTO
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
List<ProgramResponseDTO> getProgramList(ProgramReqDTO programReqDTO);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发布信发设备
|
||||||
|
* @param publishDTO
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
Boolean publishProgram(PublishDTO publishDTO);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,491 @@
|
|||||||
|
package com.cool.store.service.xinfa;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSONObject;
|
||||||
|
import com.cool.store.constants.RedisConstant;
|
||||||
|
import com.cool.store.dto.huoma.*;
|
||||||
|
import com.cool.store.enums.ErrorCodeEnum;
|
||||||
|
import com.cool.store.enums.SpecialTagEnum;
|
||||||
|
import com.cool.store.exception.ServiceException;
|
||||||
|
import com.cool.store.response.ResponseResult;
|
||||||
|
import com.cool.store.utils.RedisUtilPool;
|
||||||
|
import com.cool.store.utils.poi.constant.Constants;
|
||||||
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import okhttp3.*;
|
||||||
|
import org.apache.commons.collections4.CollectionUtils;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
|
|
||||||
|
import javax.annotation.PostConstruct;
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.text.MessageFormat;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Author suzhuhong
|
||||||
|
* @Date 2025/11/4 15:47
|
||||||
|
* @Version 1.0
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
@Slf4j
|
||||||
|
public class XinFaDeviceService {
|
||||||
|
|
||||||
|
@Value("${huoMa.direct.stores.account}")
|
||||||
|
private String huoMaDirectStoresAccount;
|
||||||
|
@Value("${huoMa.direct.stores.password}")
|
||||||
|
private String huoMaDirectStoresPassword;
|
||||||
|
@Value("${huoMa.franchise.stores.account}")
|
||||||
|
private String huoMaFranchiseStoresAccount;
|
||||||
|
@Value("${huoMa.franchise.stores.password}")
|
||||||
|
private String huoMaFranchiseStoresPassword;
|
||||||
|
@Value("${huoMa.restaurant.stores.account}")
|
||||||
|
private String huoMaRestaurantStoresAccount;
|
||||||
|
@Value("${huoMa.restaurant.stores.password}")
|
||||||
|
private String huoMaRestaurantStoresPassword;
|
||||||
|
@Resource
|
||||||
|
RedisUtilPool redisUtilPool;
|
||||||
|
@Value("${huoMa.token.url}")
|
||||||
|
private String huoMaTokenUrl;
|
||||||
|
@Value("${huoMa.get.point.terminal.url}")
|
||||||
|
private String huoMaGetPointTerminalUrl;
|
||||||
|
@Value("${huoMa.id.url}")
|
||||||
|
private String huoMaGetStoreIdUrl;
|
||||||
|
@Value("${huoMa.store.device.detail.url}")
|
||||||
|
private String huoMaGetStoreXinFaDeviceDetailUrl ;
|
||||||
|
@Value("${huoMa.get.tag.url}")
|
||||||
|
private String huoMaGetTagUrl;
|
||||||
|
@Value("${huoMa.get.program.url}")
|
||||||
|
private String huoMaGetProgramUrl;
|
||||||
|
@Value("${huoMa.get.publish.url}")
|
||||||
|
private String huoMaGetPublishUrl;
|
||||||
|
|
||||||
|
|
||||||
|
private final Map<String, HuoMaAccountDTO> accountMap = new HashMap<>();
|
||||||
|
|
||||||
|
@PostConstruct
|
||||||
|
public void initAccountMap() {
|
||||||
|
accountMap.put("restaurant", new HuoMaAccountDTO(huoMaRestaurantStoresAccount, huoMaRestaurantStoresPassword));
|
||||||
|
accountMap.put("direct", new HuoMaAccountDTO(huoMaDirectStoresAccount, huoMaDirectStoresPassword));
|
||||||
|
accountMap.put("franchise", new HuoMaAccountDTO(huoMaFranchiseStoresAccount, huoMaFranchiseStoresPassword));
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getStoreToken(String account, String password) {
|
||||||
|
String key = MessageFormat.format(RedisConstant.HUO_MA_TOKEN, account);
|
||||||
|
String accessToken = redisUtilPool.getString(key);
|
||||||
|
if (accessToken != null) {
|
||||||
|
return accessToken;
|
||||||
|
}
|
||||||
|
Map<String, String> requestBody = new HashMap<>();
|
||||||
|
requestBody.put("account", account);
|
||||||
|
requestBody.put("password", password);
|
||||||
|
String responseBody = sendPostRequest(JSONObject.toJSONString(requestBody), huoMaTokenUrl);
|
||||||
|
try{
|
||||||
|
ObjectMapper mapper = new ObjectMapper();
|
||||||
|
JsonNode rootNode = mapper.readTree(responseBody);
|
||||||
|
String token = rootNode.path("data").path("token").asText();
|
||||||
|
//缓存60秒
|
||||||
|
redisUtilPool.setString(key, token,60*60);
|
||||||
|
return token;
|
||||||
|
}catch (Exception e){
|
||||||
|
log.error("解析获取token失败,url:{},responseBody:{}",huoMaTokenUrl, responseBody);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public List<StoreEquipmentDTO> getStoreEquipmentDataByStoreNumList(List<String> storeNumList, String token) {
|
||||||
|
Map<String,List<String>> requestBody = new HashMap<>();
|
||||||
|
requestBody.put("codeList", storeNumList);
|
||||||
|
String responseBody = sendPostRequestByToken(JSONObject.toJSONString(requestBody), huoMaGetPointTerminalUrl,token);
|
||||||
|
try{
|
||||||
|
ObjectMapper mapper = new ObjectMapper();
|
||||||
|
JsonNode rootNode = mapper.readTree(responseBody);
|
||||||
|
return mapper.convertValue(rootNode.get("data"),
|
||||||
|
mapper.getTypeFactory().constructCollectionType(List.class, StoreEquipmentDTO.class));
|
||||||
|
}catch (Exception e){
|
||||||
|
log.error("解析获取data失败,url:{},responseBody:{}",huoMaTokenUrl, responseBody);
|
||||||
|
}
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public Integer getStoreIdByStoreNum(String storeNum, String token) {
|
||||||
|
String houMaStoreId = redisUtilPool.hashGet(RedisConstant.HUO_MA_STORE_ID, storeNum);
|
||||||
|
if (houMaStoreId != null) {
|
||||||
|
try {
|
||||||
|
return Integer.valueOf(houMaStoreId);
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
// 如果缓存中的数据格式不正确,继续执行正常逻辑
|
||||||
|
log.warn("Redis缓存中的门店ID格式不正确,storeNum: {}", storeNum);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
StoreRequestDTO requestBody = new StoreRequestDTO("point_report", 0, 10, storeNum);
|
||||||
|
String responseBody = sendPostRequestByToken(JSONObject.toJSONString(requestBody), huoMaGetStoreIdUrl,token);
|
||||||
|
try{
|
||||||
|
Integer storeId = extractIdsFromResponse(responseBody);
|
||||||
|
redisUtilPool.hashSet(RedisConstant.HUO_MA_STORE_ID, storeNum, storeId.toString());
|
||||||
|
return storeId;
|
||||||
|
}catch (Exception e){
|
||||||
|
log.error("解析获取data失败,url:{},responseBody:{}",huoMaTokenUrl, responseBody);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public List<StoreXinFaDeviceDetail> getStoreXinFaDeviceDetail(String storeNum) {
|
||||||
|
String source = redisUtilPool.hashGet(RedisConstant.HUOMA_STORE_DEVICE_RESOURCE_KEY, storeNum);
|
||||||
|
if (StringUtils.isNotBlank(source)) {
|
||||||
|
HuoMaAccountDTO huoMaAccountDTO = accountMap.get(source);
|
||||||
|
if (Objects.nonNull(huoMaAccountDTO)) {
|
||||||
|
String token = getStoreToken(huoMaAccountDTO.getAccount(), huoMaAccountDTO.getPassword());
|
||||||
|
List<StoreXinFaDeviceDetail> deviceDetailDetail = getStoreXinFaDeviceDetailDetail(storeNum, token);
|
||||||
|
if (CollectionUtils.isNotEmpty(deviceDetailDetail)) {
|
||||||
|
return deviceDetailDetail;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (Map.Entry<String, HuoMaAccountDTO> entry : accountMap.entrySet()) {
|
||||||
|
HuoMaAccountDTO huoMaAccountDTO = entry.getValue();
|
||||||
|
if (!huoMaAccountDTO.getIsQuery()) {
|
||||||
|
String token = getStoreToken(huoMaAccountDTO.getAccount(), huoMaAccountDTO.getPassword());
|
||||||
|
List<StoreXinFaDeviceDetail> deviceDetailDetail = getStoreXinFaDeviceDetailDetail(storeNum, token);
|
||||||
|
if (CollectionUtils.isNotEmpty(deviceDetailDetail)) {
|
||||||
|
redisUtilPool.hashSet(RedisConstant.HUOMA_STORE_DEVICE_RESOURCE_KEY, storeNum, entry.getKey(), Constants.REFRESH_TOKEN_EXPIRE);
|
||||||
|
return deviceDetailDetail;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public List<StoreXinFaDeviceDetail> getStoreXinFaDeviceDetailDetail(String storeNum, String token) {
|
||||||
|
Integer storeIdByStoreNum = getStoreIdByStoreNum(storeNum, token);
|
||||||
|
return getStoreXinFaDeviceDetailByPointId(storeIdByStoreNum, token);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public List<TagDetailDTO> getAccountAllTags(String storeNum){
|
||||||
|
String source = redisUtilPool.hashGet(RedisConstant.HUOMA_STORE_DEVICE_RESOURCE_KEY, storeNum);
|
||||||
|
//获取标签 必须要知道门店属于哪个账号下 获取对应账号下的标签 如果获取不到 直接返回空
|
||||||
|
if (StringUtils.isEmpty(source)){
|
||||||
|
log.info("门店没有找到对应的账号,storeNum: {}", storeNum);
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
|
HuoMaAccountDTO huoMaAccountDTO = accountMap.get(source);
|
||||||
|
if (Objects.nonNull(huoMaAccountDTO)){
|
||||||
|
huoMaAccountDTO.setIsQuery(true);
|
||||||
|
String token = getStoreToken(huoMaAccountDTO.getAccount(), huoMaAccountDTO.getPassword());
|
||||||
|
TagDTO tagDTO = new TagDTO("DEFAULT", 0, 30,"program");
|
||||||
|
String responseBody = null;
|
||||||
|
try{
|
||||||
|
responseBody = sendPostRequestByToken(JSONObject.toJSONString(tagDTO), huoMaGetTagUrl,token);
|
||||||
|
ObjectMapper mapper = new ObjectMapper();
|
||||||
|
JsonNode rootNode = mapper.readTree(responseBody);
|
||||||
|
|
||||||
|
// 直接转换整个数组
|
||||||
|
return mapper.convertValue(
|
||||||
|
rootNode.path("data").path("content"),
|
||||||
|
mapper.getTypeFactory().constructCollectionType(List.class, TagDetailDTO.class)
|
||||||
|
);
|
||||||
|
}catch (Exception e){
|
||||||
|
log.error("getAccountAllTags解析获取data失败,url:{},responseBody:{}",huoMaTokenUrl, responseBody);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取账号下指定标签的id 只需要一下四个
|
||||||
|
* @param storeNum
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public List<Integer> getAccountSpecialTagIds( String storeNum,List<String> tagList) {
|
||||||
|
List<TagDetailDTO> accountAllTags = getAccountAllTags(storeNum);
|
||||||
|
if (accountAllTags != null) {
|
||||||
|
return accountAllTags.stream()
|
||||||
|
.filter(tag -> tag.getName() != null &&
|
||||||
|
tagList.contains(tag.getName()))
|
||||||
|
.map(TagDetailDTO::getId)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public List<ProgramResponseDTO> getProgramList(ProgramReqDTO programReqDTO) {
|
||||||
|
if (StringUtils.isEmpty(programReqDTO.getStoreCode())){
|
||||||
|
log.info("门店没有找到对应的账号,storeNum: {}", programReqDTO.getStoreCode());
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
|
//先查询门店是属于哪个账号下
|
||||||
|
String source = redisUtilPool.hashGet(RedisConstant.HUOMA_STORE_DEVICE_RESOURCE_KEY, programReqDTO.getStoreCode());
|
||||||
|
//获取标签 必须要知道门店属于哪个账号下 获取对应账号下的标签 如果获取不到 直接返回空
|
||||||
|
if (StringUtils.isEmpty(source)){
|
||||||
|
log.info("门店没有找到对应的账号,storeNum: {}", programReqDTO.getStoreCode());
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
|
HuoMaAccountDTO huoMaAccountDTO = accountMap.get(source);
|
||||||
|
if (huoMaAccountDTO!=null){
|
||||||
|
String token = getStoreToken(huoMaAccountDTO.getAccount(), huoMaAccountDTO.getPassword());
|
||||||
|
String responseBody = null;
|
||||||
|
try{
|
||||||
|
responseBody = sendPostRequestByToken(JSONObject.toJSONString(programReqDTO), huoMaGetProgramUrl,token);
|
||||||
|
ObjectMapper mapper = new ObjectMapper();
|
||||||
|
JsonNode rootNode = mapper.readTree(responseBody);
|
||||||
|
|
||||||
|
// 直接转换整个数组
|
||||||
|
return mapper.convertValue(
|
||||||
|
rootNode.path("data").path("content"),
|
||||||
|
mapper.getTypeFactory().constructCollectionType(List.class, ProgramResponseDTO.class)
|
||||||
|
);
|
||||||
|
}catch (Exception e){
|
||||||
|
log.error("getProgramList 解析获取data失败,url:{},responseBody:{}",huoMaTokenUrl, responseBody);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Boolean publish(PublishDTO publishDTO){
|
||||||
|
if (StringUtils.isEmpty(publishDTO.getStoreCode())){
|
||||||
|
log.info("门店没有找到对应的账号,发布失败,storeNum: {}", publishDTO.getStoreCode());
|
||||||
|
return Boolean.FALSE;
|
||||||
|
}
|
||||||
|
String source = redisUtilPool.hashGet(RedisConstant.HUOMA_STORE_DEVICE_RESOURCE_KEY, publishDTO.getStoreCode());
|
||||||
|
//获取标签 必须要知道门店属于哪个账号下 获取对应账号下的标签 如果获取不到 直接返回空
|
||||||
|
if (StringUtils.isEmpty(source)){
|
||||||
|
log.info("门店没有找到对应的账号,storeNum: {}", publishDTO.getStoreCode());
|
||||||
|
return Boolean.FALSE;
|
||||||
|
}
|
||||||
|
HuoMaAccountDTO huoMaAccountDTO = accountMap.get(source);
|
||||||
|
if (huoMaAccountDTO!=null){
|
||||||
|
String token = getStoreToken(huoMaAccountDTO.getAccount(), huoMaAccountDTO.getPassword());
|
||||||
|
String responseBody = null;
|
||||||
|
try{
|
||||||
|
responseBody = sendPostRequestByToken(JSONObject.toJSONString(publishDTO), huoMaGetPublishUrl,token);
|
||||||
|
ObjectMapper mapper = new ObjectMapper();
|
||||||
|
JsonNode rootNode = mapper.readTree(responseBody);
|
||||||
|
int code = rootNode.get("code").asInt();
|
||||||
|
if (code != 0) {
|
||||||
|
throw new RuntimeException("发布失败");
|
||||||
|
}
|
||||||
|
// 直接转换整个数组
|
||||||
|
log.info("发布成功 deviceId:{},storeCode:{}",JSONObject.toJSONString(publishDTO.getDeviceIdList()), publishDTO.getStoreCode() );
|
||||||
|
return Boolean.TRUE;
|
||||||
|
}catch (Exception e){
|
||||||
|
log.error("发布失败, url:{}, responseBody:{}", huoMaTokenUrl, responseBody);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Boolean.FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public List<StoreXinFaDeviceDetail> getStoreXinFaDeviceDetailByPointId(Integer pointId, String token) {
|
||||||
|
if (pointId != null){
|
||||||
|
StoreXinFaDetailRequestDTO storeXinFaDetailRequestDTO = new StoreXinFaDetailRequestDTO(0, 10, pointId);
|
||||||
|
String responseBody = null;
|
||||||
|
try{
|
||||||
|
responseBody = sendPostRequestByToken(JSONObject.toJSONString(storeXinFaDetailRequestDTO), huoMaGetStoreXinFaDeviceDetailUrl,token);
|
||||||
|
ObjectMapper mapper = new ObjectMapper();
|
||||||
|
JsonNode rootNode = mapper.readTree(responseBody);
|
||||||
|
|
||||||
|
// 直接转换整个数组
|
||||||
|
return mapper.convertValue(
|
||||||
|
rootNode.path("data").path("content"),
|
||||||
|
mapper.getTypeFactory().constructCollectionType(List.class, StoreXinFaDeviceDetail.class)
|
||||||
|
);
|
||||||
|
}catch (Exception e){
|
||||||
|
log.error("getStoreXinFaDeviceDetailByPointId解析获取data失败,url:{},responseBody:{}",huoMaTokenUrl, responseBody);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Integer extractIdsFromResponse(String jsonResponse) throws IOException {
|
||||||
|
ObjectMapper mapper = new ObjectMapper();
|
||||||
|
JsonNode rootNode = mapper.readTree(jsonResponse);
|
||||||
|
// 遍历dataList数组提取ID
|
||||||
|
JsonNode dataList = rootNode.path("data").path("dataList");
|
||||||
|
for (JsonNode item : dataList) {
|
||||||
|
if (item.has("ID")) {
|
||||||
|
//取出第一个id
|
||||||
|
return item.get("ID").asInt();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String sendPostRequest(String requestBody, String requestUrl) {
|
||||||
|
log.info("开始发送请求,url:{},requestBody:{}", requestUrl, requestBody);
|
||||||
|
|
||||||
|
int maxRetries = 3;
|
||||||
|
for (int i = 0; i < maxRetries; i++) {
|
||||||
|
try {
|
||||||
|
Request request = new Request.Builder()
|
||||||
|
.url(requestUrl)
|
||||||
|
.post(RequestBody.create(MediaType.parse("application/json"), requestBody))
|
||||||
|
.build();
|
||||||
|
|
||||||
|
return sendPost(requestUrl, request);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.warn("请求失败,第{}次重试,错误: {}", i + 1, e.getMessage());
|
||||||
|
if (i == maxRetries - 1) {
|
||||||
|
throw new ServiceException(ErrorCodeEnum.THIRD_API_ERROR, "请求重试失败: " + e.getMessage());
|
||||||
|
}
|
||||||
|
// 重试前等待
|
||||||
|
try {
|
||||||
|
Thread.sleep(1000 * (i + 1));
|
||||||
|
} catch (InterruptedException ie) {
|
||||||
|
Thread.currentThread().interrupt();
|
||||||
|
throw new ServiceException(ErrorCodeEnum.THIRD_API_ERROR, "重试被中断");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new ServiceException(ErrorCodeEnum.THIRD_API_ERROR, "请求重试失败");
|
||||||
|
}
|
||||||
|
|
||||||
|
private String sendPostRequestByToken(String requestBody, String requestUrl, String token) {
|
||||||
|
log.info("开始发送请求,url:{},requestBody:{}", requestUrl, requestBody);
|
||||||
|
|
||||||
|
int maxRetries = 3;
|
||||||
|
for (int i = 0; i < maxRetries; i++) {
|
||||||
|
try {
|
||||||
|
Request request = new Request.Builder()
|
||||||
|
.url(requestUrl)
|
||||||
|
.post(RequestBody.create(MediaType.parse("application/json"), requestBody))
|
||||||
|
.addHeader("token", token)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
String result = sendPost(requestUrl, request);
|
||||||
|
|
||||||
|
// 检查是否token失效
|
||||||
|
if (isTokenExpired(result)) {
|
||||||
|
log.warn("Token已失效,正在清除缓存并重试,第{}次", i + 1);
|
||||||
|
// 直接清除对应账号的token缓存
|
||||||
|
token = clearAccountTokenCacheForToken(token);
|
||||||
|
|
||||||
|
// 抛出异常触发重试
|
||||||
|
throw new ServiceException(ErrorCodeEnum.THIRD_API_ERROR, "Token失效,需要重试");
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
} catch (ServiceException e) {
|
||||||
|
log.warn("请求失败,第{}次重试,错误: {}", i + 1, e.getMessage());
|
||||||
|
if (i == maxRetries - 1) {
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
Thread.sleep(1000 * (i + 1));
|
||||||
|
} catch (InterruptedException ie) {
|
||||||
|
Thread.currentThread().interrupt();
|
||||||
|
throw new ServiceException(ErrorCodeEnum.THIRD_API_ERROR, "重试被中断");
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.warn("请求异常,第{}次重试,错误: {}", i + 1, e.getMessage());
|
||||||
|
if (i == maxRetries - 1) {
|
||||||
|
throw new ServiceException(ErrorCodeEnum.THIRD_API_ERROR, "请求重试失败: " + e.getMessage());
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
Thread.sleep(1000 * (20*i + 1));
|
||||||
|
} catch (InterruptedException ie) {
|
||||||
|
Thread.currentThread().interrupt();
|
||||||
|
throw new ServiceException(ErrorCodeEnum.THIRD_API_ERROR, "重试被中断");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new ServiceException(ErrorCodeEnum.THIRD_API_ERROR, "请求重试失败");
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isTokenExpired(String responseBody) {
|
||||||
|
try {
|
||||||
|
ObjectMapper mapper = new ObjectMapper();
|
||||||
|
JsonNode rootNode = mapper.readTree(responseBody);
|
||||||
|
int code = rootNode.path("code").asInt(-1);
|
||||||
|
String msg = rootNode.path("msg").asText("");
|
||||||
|
|
||||||
|
return code == 501;
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("检查token失效状态时发生错误: {}", e.getMessage());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String clearAccountTokenCacheForToken(String token) {
|
||||||
|
try {
|
||||||
|
// 遍历可能的账号,找到对应的缓存并删除
|
||||||
|
String[] accounts = {
|
||||||
|
huoMaDirectStoresAccount,
|
||||||
|
huoMaFranchiseStoresAccount,
|
||||||
|
huoMaRestaurantStoresAccount
|
||||||
|
};
|
||||||
|
|
||||||
|
for (String account : accounts) {
|
||||||
|
if (account != null) {
|
||||||
|
String key = MessageFormat.format(RedisConstant.HUO_MA_TOKEN, account);
|
||||||
|
String cachedToken = redisUtilPool.getString(key);
|
||||||
|
if (token.equals(cachedToken)) {
|
||||||
|
redisUtilPool.delKey(key);
|
||||||
|
log.info("已清除账号 {} 的token缓存", account);
|
||||||
|
|
||||||
|
// 根据账号类型获取对应的密码并重新获取token
|
||||||
|
String password = getPasswordForAccount(account);
|
||||||
|
if (password != null) {
|
||||||
|
String newToken = getStoreToken(account, password);
|
||||||
|
if (newToken != null) {
|
||||||
|
log.info("已为账号 {} 重新获取新的token", account);
|
||||||
|
return newToken;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("清除token缓存或重新获取token失败: {}", e.getMessage());
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private String getPasswordForAccount(String account) {
|
||||||
|
if (account.equals(huoMaDirectStoresAccount)) {
|
||||||
|
return huoMaDirectStoresPassword;
|
||||||
|
} else if (account.equals(huoMaFranchiseStoresAccount)) {
|
||||||
|
return huoMaFranchiseStoresPassword;
|
||||||
|
} else if (account.equals(huoMaRestaurantStoresAccount)) {
|
||||||
|
return huoMaRestaurantStoresPassword;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private static String sendPost(String requestUrl, Request request) {
|
||||||
|
try (Response response = new OkHttpClient().newCall(request).execute()) {
|
||||||
|
log.info("发起请求 time:{}", System.currentTimeMillis());
|
||||||
|
if (!response.isSuccessful()) {
|
||||||
|
log.info("HTTP请求失败,msg: " + response.message());
|
||||||
|
throw new ServiceException(ErrorCodeEnum.THIRD_API_ERROR,
|
||||||
|
"HTTP请求失败,状态码: " + response.code());
|
||||||
|
}
|
||||||
|
String responseBody = response.body().string();
|
||||||
|
log.info("请求成功responseBody:{}", JSONObject.toJSONString(responseBody));
|
||||||
|
return responseBody;
|
||||||
|
} catch (ServiceException e) {
|
||||||
|
throw e;
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("API调用异常 - URL: {}, 错误: {}", requestUrl, e.getMessage(), e);
|
||||||
|
throw new ServiceException(ErrorCodeEnum.THIRD_API_ERROR, "接口调用异常: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -220,4 +220,6 @@ public class Constants
|
|||||||
|
|
||||||
public static final String WANG_LEI_JOB_NUMBER = "19060164";
|
public static final String WANG_LEI_JOB_NUMBER = "19060164";
|
||||||
|
|
||||||
|
public static final int REFRESH_TOKEN_EXPIRE = 60*60*24*30;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,6 +42,11 @@ public class OpenApiValidateFilter implements Filter {
|
|||||||
private String coolAppKey;
|
private String coolAppKey;
|
||||||
@Value("${cool.api.secret}")
|
@Value("${cool.api.secret}")
|
||||||
private String coolAppSecret;
|
private String coolAppSecret;
|
||||||
|
private static final Set<String> WHITELIST_URIS = new HashSet<>(Arrays.asList(
|
||||||
|
"/zxjp/open/v1/statusRefresh",
|
||||||
|
"/zxjp/open/v1/getStoreUser",
|
||||||
|
"/zxjp/open/v1/callback"
|
||||||
|
));
|
||||||
private static final List<String> oldUrlMapping = new ArrayList<>(Arrays.asList(
|
private static final List<String> oldUrlMapping = new ArrayList<>(Arrays.asList(
|
||||||
"/zxjp/open/v1/statusRefresh","/zxjp/open/v1/changePaymentStatus",
|
"/zxjp/open/v1/statusRefresh","/zxjp/open/v1/changePaymentStatus",
|
||||||
"/zxjp/open/v1/getYlsToken", "/zxjp/open/v1/getStoreList",
|
"/zxjp/open/v1/getYlsToken", "/zxjp/open/v1/getStoreList",
|
||||||
@@ -61,7 +66,7 @@ public class OpenApiValidateFilter implements Filter {
|
|||||||
}
|
}
|
||||||
MDC.put(CommonConstants.REQUEST_ID, UUIDUtils.get32UUID());
|
MDC.put(CommonConstants.REQUEST_ID, UUIDUtils.get32UUID());
|
||||||
//statusRefresh 放开不需要验签
|
//statusRefresh 放开不需要验签
|
||||||
if (uri.startsWith("/zxjp/open/v1/statusRefresh") || uri.startsWith("/zxjp/open/v1/getStoreUser")) {
|
if (isWhitelistUri(uri)) {
|
||||||
filterChain.doFilter(servletRequest, response);
|
filterChain.doFilter(servletRequest, response);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -174,6 +179,9 @@ public class OpenApiValidateFilter implements Filter {
|
|||||||
return OpenSignatureUtil.generateOldSign(params, coolAppSecret);
|
return OpenSignatureUtil.generateOldSign(params, coolAppSecret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isWhitelistUri(String uri) {
|
||||||
|
return WHITELIST_URIS.stream().anyMatch(uri::startsWith);
|
||||||
|
}
|
||||||
@Override
|
@Override
|
||||||
public void destroy() {
|
public void destroy() {
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,37 @@
|
|||||||
|
package com.cool.store.controller.webb;
|
||||||
|
|
||||||
|
import com.cool.store.request.recipe.RevenueDataRequest;
|
||||||
|
import com.cool.store.response.ResponseResult;
|
||||||
|
import com.cool.store.service.ThirdFoodService;
|
||||||
|
import com.cool.store.vo.recipe.RevenueDataVO;
|
||||||
|
import io.swagger.annotations.Api;
|
||||||
|
import io.swagger.annotations.ApiOperation;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import javax.validation.Valid;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 数据看板 前端控制器
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author wangff
|
||||||
|
* @since 2025/10/30
|
||||||
|
*/
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/pc/databoard")
|
||||||
|
@Api(tags = "数据看板")
|
||||||
|
@Slf4j
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class DataBoardController {
|
||||||
|
private final ThirdFoodService thirdFoodService;
|
||||||
|
|
||||||
|
@ApiOperation("门店营收")
|
||||||
|
@PostMapping("/revenueData")
|
||||||
|
public ResponseResult<List<RevenueDataVO>> getStoreRevenueData(@RequestBody @Valid RevenueDataRequest request) {
|
||||||
|
return ResponseResult.success(thirdFoodService.getRevenueData(request));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,6 +5,7 @@ import com.cool.store.context.PartnerUserHolder;
|
|||||||
import com.cool.store.dto.*;
|
import com.cool.store.dto.*;
|
||||||
import com.cool.store.dto.store.StoreUserPositionDTO;
|
import com.cool.store.dto.store.StoreUserPositionDTO;
|
||||||
import com.cool.store.dto.wx.MiniProgramFreeLoginDTO;
|
import com.cool.store.dto.wx.MiniProgramFreeLoginDTO;
|
||||||
|
import com.cool.store.handler.WeChatHandler;
|
||||||
import com.cool.store.request.OpenApiStoreRequest;
|
import com.cool.store.request.OpenApiStoreRequest;
|
||||||
import com.cool.store.request.StoreCodeDTO;
|
import com.cool.store.request.StoreCodeDTO;
|
||||||
import com.cool.store.request.*;
|
import com.cool.store.request.*;
|
||||||
@@ -15,10 +16,12 @@ import com.cool.store.request.xgj.ReceiptCallBackRequest;
|
|||||||
import com.cool.store.response.ResponseResult;
|
import com.cool.store.response.ResponseResult;
|
||||||
import com.cool.store.response.bigdata.ApiResponse;
|
import com.cool.store.response.bigdata.ApiResponse;
|
||||||
import com.cool.store.service.*;
|
import com.cool.store.service.*;
|
||||||
|
import com.cool.store.utils.poi.StringUtils;
|
||||||
import com.github.pagehelper.PageInfo;
|
import com.github.pagehelper.PageInfo;
|
||||||
import io.swagger.annotations.Api;
|
import io.swagger.annotations.Api;
|
||||||
import io.swagger.annotations.ApiOperation;
|
import io.swagger.annotations.ApiOperation;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
@@ -52,6 +55,8 @@ public class OpenApiController {
|
|||||||
MessageTemplateService messageTemplateService;
|
MessageTemplateService messageTemplateService;
|
||||||
@Resource
|
@Resource
|
||||||
WechatMiniAppService wechatMiniAppService;
|
WechatMiniAppService wechatMiniAppService;
|
||||||
|
@Autowired
|
||||||
|
WeChatHandler weChatHandler;
|
||||||
|
|
||||||
@PostMapping("/statusRefresh")
|
@PostMapping("/statusRefresh")
|
||||||
public ApiResponse<Boolean> statusRefresh(@RequestBody StatusRefreshDTO statusRefreshDTO){
|
public ApiResponse<Boolean> statusRefresh(@RequestBody StatusRefreshDTO statusRefreshDTO){
|
||||||
@@ -185,4 +190,28 @@ public class OpenApiController {
|
|||||||
public ApiResponse<String> getTokenByMobile(@RequestBody @Validated MiniProgramFreeLoginDTO param) {
|
public ApiResponse<String> getTokenByMobile(@RequestBody @Validated MiniProgramFreeLoginDTO param) {
|
||||||
return ApiResponse.success(wechatMiniAppService.getShortTermTokenByMobile(param));
|
return ApiResponse.success(wechatMiniAppService.getShortTermTokenByMobile(param));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@RequestMapping(value = "/callback", produces = "application/xml;charset=UTF-8")
|
||||||
|
@ApiOperation("callback")
|
||||||
|
public String handleWechatMessage(
|
||||||
|
@RequestParam("signature") String signature,
|
||||||
|
@RequestParam("timestamp") String timestamp,
|
||||||
|
@RequestParam("nonce") String nonce,
|
||||||
|
@RequestParam(value = "echostr", required = false) String echostr,
|
||||||
|
@RequestBody(required = false) String requestBody) {
|
||||||
|
|
||||||
|
log.info("url:{}","/open/v1/");
|
||||||
|
log.info("callback_signature:{},timestamp:{},nonce:{}",signature,timestamp,nonce);
|
||||||
|
log.info("requestBody:{}",requestBody);
|
||||||
|
|
||||||
|
if (StringUtils.isNotEmpty(requestBody)) {
|
||||||
|
try {
|
||||||
|
return weChatHandler.processMessage(weChatHandler.parseXmlToMap(requestBody));
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.info("回调处理失败 e:{}",e);
|
||||||
|
return "success";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return echostr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,11 +8,16 @@ import com.cool.store.dto.FoodTokenDTO;
|
|||||||
import com.cool.store.dto.GetAccessTokenDTO;
|
import com.cool.store.dto.GetAccessTokenDTO;
|
||||||
import com.cool.store.dto.HqtTokenDTO;
|
import com.cool.store.dto.HqtTokenDTO;
|
||||||
import com.cool.store.dto.ModifyPasswordDTO;
|
import com.cool.store.dto.ModifyPasswordDTO;
|
||||||
|
import com.cool.store.dto.huoma.*;
|
||||||
|
import com.cool.store.dto.wechat.CallbackMessageDTO;
|
||||||
|
import com.cool.store.dto.wechat.WechatTemplateMessageDTO;
|
||||||
import com.cool.store.entity.*;
|
import com.cool.store.entity.*;
|
||||||
import com.cool.store.enums.DownSystemTypeEnum;
|
import com.cool.store.enums.DownSystemTypeEnum;
|
||||||
import com.cool.store.enums.MessageEnum;
|
import com.cool.store.enums.MessageEnum;
|
||||||
import com.cool.store.enums.SMSMsgEnum;
|
import com.cool.store.enums.SMSMsgEnum;
|
||||||
import com.cool.store.enums.point.ShopSubStageStatusEnum;
|
import com.cool.store.enums.point.ShopSubStageStatusEnum;
|
||||||
|
import com.cool.store.enums.wechat.WechatTemplateEnum;
|
||||||
|
import com.cool.store.handler.WeChatHandler;
|
||||||
import com.cool.store.job.XxlJobHandler;
|
import com.cool.store.job.XxlJobHandler;
|
||||||
import com.cool.store.mapper.FranchiseFeeMapper;
|
import com.cool.store.mapper.FranchiseFeeMapper;
|
||||||
import com.cool.store.mapper.LineInfoMapper;
|
import com.cool.store.mapper.LineInfoMapper;
|
||||||
@@ -36,10 +41,14 @@ import com.cool.store.service.*;
|
|||||||
import com.cool.store.service.impl.CommonService;
|
import com.cool.store.service.impl.CommonService;
|
||||||
import com.cool.store.service.impl.OrderSysInfoServiceImpl;
|
import com.cool.store.service.impl.OrderSysInfoServiceImpl;
|
||||||
import com.cool.store.service.impl.UserAuthMappingServiceImpl;
|
import com.cool.store.service.impl.UserAuthMappingServiceImpl;
|
||||||
|
import com.cool.store.service.wechat.WechatTemplateService;
|
||||||
|
import com.cool.store.service.xinfa.XinFaBusinessService;
|
||||||
|
import com.cool.store.service.xinfa.XinFaDeviceService;
|
||||||
import com.cool.store.utils.CoolDateUtils;
|
import com.cool.store.utils.CoolDateUtils;
|
||||||
import com.cool.store.utils.RedisConstantUtil;
|
import com.cool.store.utils.RedisConstantUtil;
|
||||||
import com.cool.store.utils.RedisUtilPool;
|
import com.cool.store.utils.RedisUtilPool;
|
||||||
import com.cool.store.utils.poi.StringUtils;
|
import com.cool.store.utils.poi.StringUtils;
|
||||||
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
import io.swagger.annotations.ApiOperation;
|
import io.swagger.annotations.ApiOperation;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
@@ -92,14 +101,16 @@ public class PCTestController {
|
|||||||
private HttpRestTemplateService httpRestTemplateService;
|
private HttpRestTemplateService httpRestTemplateService;
|
||||||
@Resource
|
@Resource
|
||||||
FranchiseFeeMapper franchiseFeeMapper;
|
FranchiseFeeMapper franchiseFeeMapper;
|
||||||
|
@Resource
|
||||||
|
WechatTemplateService wechatTemplateService;
|
||||||
@Resource
|
@Resource
|
||||||
ShopInfoMapper shopInfoMapper;
|
ShopInfoMapper shopInfoMapper;
|
||||||
@Resource
|
@Resource
|
||||||
LinePayService linePayService;
|
LinePayService linePayService;
|
||||||
@Resource
|
@Resource
|
||||||
LinePayDAO linePayDAO;
|
LinePayDAO linePayDAO;
|
||||||
|
@Autowired
|
||||||
|
WeChatHandler weChatHandler;
|
||||||
@GetMapping("/syncStore")
|
@GetMapping("/syncStore")
|
||||||
public ResponseResult<Boolean> syncStore(@RequestParam("shopId")Long shopId){
|
public ResponseResult<Boolean> syncStore(@RequestParam("shopId")Long shopId){
|
||||||
syncMainSysServer.syncStore(shopId);
|
syncMainSysServer.syncStore(shopId);
|
||||||
@@ -556,4 +567,75 @@ public class PCTestController {
|
|||||||
return request;
|
return request;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@RequestMapping(value = "/testWxNotice", produces = "application/xml;charset=UTF-8")
|
||||||
|
@ApiOperation("testWxNotice")
|
||||||
|
public String handleWechatMessage(
|
||||||
|
@RequestParam("signature") String signature,
|
||||||
|
@RequestParam("timestamp") String timestamp,
|
||||||
|
@RequestParam("nonce") String nonce,
|
||||||
|
@RequestParam(value = "echostr", required = false) String echostr,
|
||||||
|
@RequestBody(required = false) String requestBody) {
|
||||||
|
|
||||||
|
System.out.println("收到微信消息:");
|
||||||
|
System.out.println("signature: " + signature);
|
||||||
|
System.out.println("timestamp: " + timestamp);
|
||||||
|
System.out.println("nonce: " + nonce);
|
||||||
|
System.out.println("echostr: " + echostr);
|
||||||
|
System.out.println("requestBody: " + requestBody);
|
||||||
|
|
||||||
|
if (StringUtils.isNotEmpty(requestBody)) {
|
||||||
|
try {
|
||||||
|
return weChatHandler.processMessage(weChatHandler.parseXmlToMap(requestBody));
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.info("回调处理失败 e:{}",e.getMessage());
|
||||||
|
return "success";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nonce;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ApiOperation("测试小程序模板消息")
|
||||||
|
@PostMapping("/testMiniAppTemplate")
|
||||||
|
public ApiResponse<Boolean> testMiniAppTemplate() {
|
||||||
|
Map<String, Object> data = new HashMap<>();
|
||||||
|
data.put("character_string2", "ceshi002");
|
||||||
|
data.put("thing10", "测试通知功能");
|
||||||
|
data.put("time14", "2025-10-01 12:00:00");
|
||||||
|
data.put("thing25", "正新管理有限公司");
|
||||||
|
data.put("thing60", "上海市-松江区");
|
||||||
|
wechatTemplateService.sendNormalTemplate("o9_unvpJy1SGdnkeun7igRBSLuB0", WechatTemplateEnum.QUESTION_NOTICE, data);
|
||||||
|
return ApiResponse.success(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
XinFaBusinessService xinFaBusinessService;
|
||||||
|
@ApiOperation("测试门店设备信息")
|
||||||
|
@GetMapping("/getStoreXinFaDeviceDetail")
|
||||||
|
public ResponseResult<List<StoreXinFaDeviceDetail>> getStoreXinFaDeviceDetail(@RequestParam("storeNum")String storeNum) {
|
||||||
|
return ResponseResult.success(xinFaBusinessService.getStoreXinFaDeviceDetail(storeNum));
|
||||||
|
}
|
||||||
|
|
||||||
|
@ApiOperation("测试标签信息")
|
||||||
|
@GetMapping("/getAccountAllTags")
|
||||||
|
public ResponseResult<List<TagDetailDTO>> getAccountAllTags(@RequestParam("storeNum")String storeNum,
|
||||||
|
@RequestParam("deviceName")String deviceName) {
|
||||||
|
List<TagDetailDTO> accountAllTags = xinFaBusinessService.getAccountAllTags(storeNum,deviceName);
|
||||||
|
return ResponseResult.success(accountAllTags);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ApiOperation("获取节目列表")
|
||||||
|
@PostMapping("/getProgramList")
|
||||||
|
public ResponseResult<List<ProgramResponseDTO>> getProgramList(@RequestBody ProgramReqDTO programReqDTO) {
|
||||||
|
List<ProgramResponseDTO> accountAllTags = xinFaBusinessService.getProgramList(programReqDTO);
|
||||||
|
return ResponseResult.success(accountAllTags);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ApiOperation("发布/上架")
|
||||||
|
@PostMapping("/publishProgram")
|
||||||
|
public ResponseResult<Boolean> publishProgram(@RequestBody PublishDTO publishDTO) {
|
||||||
|
Boolean publishStatus = xinFaBusinessService.publishProgram(publishDTO);
|
||||||
|
return ResponseResult.success(publishStatus);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,47 @@
|
|||||||
|
package com.cool.store.controller.webc;
|
||||||
|
|
||||||
|
import com.cool.store.dto.recipe.RecipeSpLaunchDTO;
|
||||||
|
import com.cool.store.request.recipe.RevenueDataRequest;
|
||||||
|
import com.cool.store.response.ResponseResult;
|
||||||
|
import com.cool.store.service.ThirdFoodService;
|
||||||
|
import com.cool.store.vo.recipe.RevenueDataVO;
|
||||||
|
import io.swagger.annotations.Api;
|
||||||
|
import io.swagger.annotations.ApiOperation;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import javax.validation.Valid;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 数据看板 前端控制器
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author wangff
|
||||||
|
* @since 2025/10/30
|
||||||
|
*/
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/mini/databoard")
|
||||||
|
@Api(tags = "Mini数据看板")
|
||||||
|
@Slf4j
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class MiniDataBoardController {
|
||||||
|
private final ThirdFoodService thirdFoodService;
|
||||||
|
|
||||||
|
@ApiOperation("门店营收")
|
||||||
|
@PostMapping("/revenueData")
|
||||||
|
public ResponseResult<List<RevenueDataVO>> getStoreRevenueData(@RequestBody @Valid RevenueDataRequest request) {
|
||||||
|
return ResponseResult.success(thirdFoodService.getRevenueData(request));
|
||||||
|
}
|
||||||
|
|
||||||
|
@ApiOperation("查询菜品服务包上新数据")
|
||||||
|
@PostMapping("/recipeSpLaunch")
|
||||||
|
public ResponseResult<RecipeSpLaunchDTO> getRecipeSpLaunchData(@RequestBody @Valid RevenueDataRequest request) {
|
||||||
|
return ResponseResult.success(thirdFoodService.getRecipeServiceLaunch(request));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
package com.cool.store.controller.webc;
|
||||||
|
|
||||||
|
import com.cool.store.dto.huoma.*;
|
||||||
|
import com.cool.store.response.ResponseResult;
|
||||||
|
import com.cool.store.service.xinfa.XinFaBusinessService;
|
||||||
|
import io.swagger.annotations.Api;
|
||||||
|
import io.swagger.annotations.ApiOperation;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Author suzhuhong
|
||||||
|
* @Date 2025/11/5 17:49
|
||||||
|
* @Version 1.0
|
||||||
|
*/
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/mini/xinfa")
|
||||||
|
@Api(tags = "小程序-信发")
|
||||||
|
@Slf4j
|
||||||
|
public class MiniXinFaController {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
XinFaBusinessService xinFaBusinessService;
|
||||||
|
@ApiOperation("测试门店设备信息")
|
||||||
|
@GetMapping("/getStoreXinFaDeviceDetail")
|
||||||
|
public ResponseResult<List<StoreXinFaDeviceDetail>> getStoreXinFaDeviceDetail(@RequestParam("storeNum")String storeNum) {
|
||||||
|
return ResponseResult.success(xinFaBusinessService.getStoreXinFaDeviceDetail(storeNum));
|
||||||
|
}
|
||||||
|
|
||||||
|
@ApiOperation("测试标签信息")
|
||||||
|
@PostMapping("/getAccountAllTags")
|
||||||
|
public ResponseResult<List<TagDetailDTO>> getAccountAllTags(@RequestBody AccountTagDTO tagDTO) {
|
||||||
|
List<TagDetailDTO> accountAllTags = xinFaBusinessService.getAccountAllTags(tagDTO.getStoreNum(), tagDTO.getDeviceName());
|
||||||
|
return ResponseResult.success(accountAllTags);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ApiOperation("获取节目列表")
|
||||||
|
@PostMapping("/getProgramList")
|
||||||
|
public ResponseResult<List<ProgramResponseDTO>> getProgramList(@RequestBody ProgramReqDTO programReqDTO) {
|
||||||
|
List<ProgramResponseDTO> accountAllTags = xinFaBusinessService.getProgramList(programReqDTO);
|
||||||
|
return ResponseResult.success(accountAllTags);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ApiOperation("发布/上架")
|
||||||
|
@PostMapping("/publishProgram")
|
||||||
|
public ResponseResult<Boolean> publishProgram(@RequestBody PublishDTO publishDTO) {
|
||||||
|
Boolean publishStatus = xinFaBusinessService.publishProgram(publishDTO);
|
||||||
|
return ResponseResult.success(publishStatus);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -137,3 +137,22 @@ hqt.token.grant_type=client_credentials
|
|||||||
hqt.token.client.id=WrPffdGpcWkcPsbN
|
hqt.token.client.id=WrPffdGpcWkcPsbN
|
||||||
hqt.token.client.secret=rYe9Cwug5LwQNIBJAiW0a7weF9CAhYCD
|
hqt.token.client.secret=rYe9Cwug5LwQNIBJAiW0a7weF9CAhYCD
|
||||||
|
|
||||||
|
#fuwuhao appId
|
||||||
|
wechat.mp.appId=wx4a18ef8bb41aa55c
|
||||||
|
wechat.mp.appSecret=793904b58f4ecdead3bbe4312c5f5c45
|
||||||
|
#xiaochengxu appid
|
||||||
|
wechat.miniapp.appId=wxd77a2761c1911ee1
|
||||||
|
|
||||||
|
huoMa.token.url = https://www.huoMayunping.com/api/SAASLogin/merchant
|
||||||
|
huoMa.id.url = https://www.huomayunping.com/api/reportCenter/executeSql
|
||||||
|
huoMa.store.device.detail.url = https://www.huomayunping.com/api/terminal/search
|
||||||
|
huoMa.get.point.terminal.url = https://www.huoMayunping.com/api/terminal/getPointTerminalInfos
|
||||||
|
huoMa.get.tag.url = https://www.huomayunping.com/api/tag/search
|
||||||
|
huoMa.get.program.url = https://www.huomayunping.com/api/program/search
|
||||||
|
huoMa.get.publish.url = https://www.huomayunping.com/api/channelPublish/target/v2/quick-publish
|
||||||
|
huoMa.direct.stores.account = 15370309163
|
||||||
|
huoMa.direct.stores.password = Zx@123456.
|
||||||
|
huoMa.franchise.stores.account = 13563273279
|
||||||
|
huoMa.franchise.stores.password = Zx@123456.
|
||||||
|
huoMa.restaurant.stores.account = 18656552865
|
||||||
|
huoMa.restaurant.stores.password = ZX123456
|
||||||
|
|||||||
@@ -138,4 +138,24 @@ hqt.token.url=https://tc.cloud.hecom.cn
|
|||||||
hqt.token.username=18161486722
|
hqt.token.username=18161486722
|
||||||
hqt.token.grant_type=client_credentials
|
hqt.token.grant_type=client_credentials
|
||||||
hqt.token.client.id=WrPffdGpcWkcPsbN
|
hqt.token.client.id=WrPffdGpcWkcPsbN
|
||||||
hqt.token.client.secret=rYe9Cwug5LwQNIBJAiW0a7weF9CAhYCD
|
hqt.token.client.secret=rYe9Cwug5LwQNIBJAiW0a7weF9CAhYCD
|
||||||
|
|
||||||
|
#fuwuhao appId
|
||||||
|
wechat.mp.appId=wx4a18ef8bb41aa55c
|
||||||
|
wechat.mp.appSecret=793904b58f4ecdead3bbe4312c5f5c45
|
||||||
|
#xiaochengxu appid
|
||||||
|
wechat.miniapp.appId=wxd77a2761c1911ee1
|
||||||
|
|
||||||
|
huoMa.token.url = https://www.huoMayunping.com/api/SAASLogin/merchant
|
||||||
|
huoMa.id.url = https://www.huomayunping.com/api/reportCenter/executeSql
|
||||||
|
huoMa.store.device.detail.url = https://www.huomayunping.com/api/terminal/search
|
||||||
|
huoMa.get.point.terminal.url = https://www.huoMayunping.com/api/terminal/getPointTerminalInfos
|
||||||
|
huoMa.get.tag.url = https://www.huomayunping.com/api/tag/search
|
||||||
|
huoMa.get.program.url = https://www.huomayunping.com/api/program/search
|
||||||
|
huoMa.get.publish.url = https://www.huomayunping.com/api/channelPublish/target/v2/quick-publish
|
||||||
|
huoMa.direct.stores.account = 15370309163
|
||||||
|
huoMa.direct.stores.password = Zx@123456.
|
||||||
|
huoMa.franchise.stores.account = 13563273279
|
||||||
|
huoMa.franchise.stores.password = Zx@123456.
|
||||||
|
huoMa.restaurant.stores.account = 18656552865
|
||||||
|
huoMa.restaurant.stores.password = ZX123456
|
||||||
@@ -145,3 +145,27 @@ hqt.token.grant_type=client_credentials
|
|||||||
hqt.token.client.id=WrPffdGpcWkcPsbN
|
hqt.token.client.id=WrPffdGpcWkcPsbN
|
||||||
hqt.token.client.secret=rYe9Cwug5LwQNIBJAiW0a7weF9CAhYCD
|
hqt.token.client.secret=rYe9Cwug5LwQNIBJAiW0a7weF9CAhYCD
|
||||||
|
|
||||||
|
|
||||||
|
#fuwuhao appId
|
||||||
|
wechat.mp.appId=wx4a18ef8bb41aa55c
|
||||||
|
wechat.mp.appSecret=793904b58f4ecdead3bbe4312c5f5c45
|
||||||
|
#xiaochengxu appid
|
||||||
|
wechat.miniapp.appId=wxd77a2761c1911ee1
|
||||||
|
|
||||||
|
zx.iot.appId=p-ts3PhNyf
|
||||||
|
zx.iot.appSecret=X4cVmfxM+
|
||||||
|
|
||||||
|
|
||||||
|
huoMa.token.url = https://www.huoMayunping.com/api/SAASLogin/merchant
|
||||||
|
huoMa.id.url = https://www.huomayunping.com/api/reportCenter/executeSql
|
||||||
|
huoMa.store.device.detail.url = https://www.huomayunping.com/api/terminal/search
|
||||||
|
huoMa.get.point.terminal.url = https://www.huoMayunping.com/api/terminal/getPointTerminalInfos
|
||||||
|
huoMa.get.tag.url = https://www.huomayunping.com/api/tag/search
|
||||||
|
huoMa.get.program.url = https://www.huomayunping.com/api/program/search
|
||||||
|
huoMa.get.publish.url = https://www.huomayunping.com/api/channelPublish/target/v2/quick-publish
|
||||||
|
huoMa.direct.stores.account = 15370309163
|
||||||
|
huoMa.direct.stores.password = Zx@123456.
|
||||||
|
huoMa.franchise.stores.account = 13563273279
|
||||||
|
huoMa.franchise.stores.password = Zx@123456.
|
||||||
|
huoMa.restaurant.stores.account = 18656552865
|
||||||
|
huoMa.restaurant.stores.password = ZX123456
|
||||||
|
|||||||
1
pom.xml
1
pom.xml
@@ -232,6 +232,7 @@
|
|||||||
<artifactId>alibabacloud-dysmsapi20170525</artifactId>
|
<artifactId>alibabacloud-dysmsapi20170525</artifactId>
|
||||||
<version>2.0.24</version>
|
<version>2.0.24</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<!-- XML处理 -->
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</dependencyManagement>
|
</dependencyManagement>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user