diff --git a/yudao-dependencies/pom.xml b/yudao-dependencies/pom.xml
index 4ecaa83e29..693ac35ecf 100644
--- a/yudao-dependencies/pom.xml
+++ b/yudao-dependencies/pom.xml
@@ -72,6 +72,13 @@
2.0.5
1.8.1
4.6.0
+
+ 11.9.1
+ 11.9.1
+ 11.9.1
+ 11.9.1
+ 3.12.0
+
@@ -592,6 +599,40 @@
org.eclipse.paho.client.mqttv3
${mqtt.version}
+
+
+
+
+ org.apache.commons
+ commons-lang3
+ ${commons-lang3.version}
+
+
+
+
+ io.github.openfeign
+ feign-core
+ ${feign-core.version}
+
+
+
+ io.github.openfeign
+ feign-jackson
+ ${feign-jackson.version}
+
+
+
+ io.github.openfeign
+ feign-okhttp
+ ${feign-okhttp.version}
+
+
+
+ io.github.openfeign
+ feign-slf4j
+ ${feign-slf4j.version}
+
+
diff --git a/yudao-module-haoka/yudao-module-haoka-biz/pom.xml b/yudao-module-haoka/yudao-module-haoka-biz/pom.xml
index a76691c5a3..4dcf160a92 100644
--- a/yudao-module-haoka/yudao-module-haoka-biz/pom.xml
+++ b/yudao-module-haoka/yudao-module-haoka-biz/pom.xml
@@ -67,6 +67,31 @@
cn.iocoder.boot
yudao-spring-boot-starter-biz-tenant
+
+
+ com.doudian.open
+ doudian-sdk-java
+ 1.1.0
+ system
+ ${project.basedir}/src/main/resources/lib/doudian-sdk-java-1.1.0.jar
+
+
+
+ io.github.openfeign
+ feign-core
+
+
+ io.github.openfeign
+ feign-jackson
+
+
+ io.github.openfeign
+ feign-okhttp
+
+
+ io.github.openfeign
+ feign-slf4j
+
diff --git a/yudao-module-haoka/yudao-module-haoka-biz/src/main/java/cn/iocoder/yudao/module/haoka/qetesh/CustomizeDatabind.java b/yudao-module-haoka/yudao-module-haoka-biz/src/main/java/cn/iocoder/yudao/module/haoka/qetesh/CustomizeDatabind.java
new file mode 100644
index 0000000000..70146cc9a4
--- /dev/null
+++ b/yudao-module-haoka/yudao-module-haoka-biz/src/main/java/cn/iocoder/yudao/module/haoka/qetesh/CustomizeDatabind.java
@@ -0,0 +1,117 @@
+package cn.iocoder.yudao.module.haoka.qetesh;
+
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.JsonDeserializer;
+import com.fasterxml.jackson.databind.JsonSerializer;
+import com.fasterxml.jackson.databind.SerializerProvider;
+
+import java.io.IOException;
+import java.sql.Timestamp;
+import java.time.Instant;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
+import java.time.ZoneId;
+import java.util.List;
+
+import static org.apache.commons.lang3.ObjectUtils.isNotEmpty;
+
+/**
+ * 允许进行特定是序列化和反序列化
+ */
+public class CustomizeDatabind {
+
+ public static class EscapedOrListToString extends JsonDeserializer> {
+
+ @Override
+ public List deserialize(JsonParser p, DeserializationContext ctxt)
+ throws IOException, JsonProcessingException {
+ if (p.currentToken().isStructStart()) {
+ //list
+ return p.readValueAs(new TypeReference>() {
+ });
+ } else {
+ //string
+ String valueAsString = p.getValueAsString();
+ return JacksonHolder.objectMapper.readValue(valueAsString,
+ new TypeReference>() {
+ });
+ }
+ }
+ }
+
+ public static class EpochMilliToLocalDateTime extends JsonSerializer {
+ @Override
+ public void serialize(Long value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
+ LocalDateTime localDateTime = Instant.ofEpochMilli(value).atZone(ZoneId.systemDefault()).toLocalDateTime();
+ gen.writeString(localDateTime.toString());
+ }
+ }
+
+
+ public static class StrToLongDeserializer extends JsonDeserializer {
+ @Override
+ public Long deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
+ return Long.valueOf(p.getValueAsString());
+ }
+ }
+
+ public static class LongToStrSerializer extends JsonSerializer {
+ @Override
+ public void serialize(Long value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
+ gen.writeString(String.valueOf(value));
+ }
+ }
+
+ public static class TsStrDeserializer extends JsonDeserializer {
+ @Override
+ public Timestamp deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
+ if (isNotEmpty(p.getLongValue())) {
+ return new Timestamp(p.getLongValue());
+ }
+ return null;
+ }
+ }
+
+
+ public static class InstantToLongSerializer extends JsonSerializer {
+ @Override
+ public void serialize(Instant value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
+ gen.writeNumber(value.toEpochMilli());
+ }
+ }
+
+ public static class LongToInstantDeserializer extends JsonDeserializer {
+ @Override
+ public Instant deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
+ return Instant.ofEpochMilli(p.getLongValue());
+ }
+ }
+
+ public static class LocalTimeToString extends JsonSerializer {
+ @Override
+ public void serialize(LocalTime value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
+ if (value.equals(LocalTime.MAX)) {
+ gen.writeString("24:00");
+ } else {
+ gen.writeString(value.toString());
+ }
+ }
+ }
+
+ public static class StringToLocalTime extends JsonDeserializer {
+
+ @Override
+ public LocalTime deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
+ if (p.getValueAsString().startsWith("24:")) {
+ return LocalTime.MAX;
+ } else {
+ return LocalTime.parse(p.getValueAsString());
+ }
+ }
+ }
+
+}
diff --git a/yudao-module-haoka/yudao-module-haoka-biz/src/main/java/cn/iocoder/yudao/module/haoka/qetesh/JacksonHolder.java b/yudao-module-haoka/yudao-module-haoka-biz/src/main/java/cn/iocoder/yudao/module/haoka/qetesh/JacksonHolder.java
new file mode 100644
index 0000000000..6ad39fbcaf
--- /dev/null
+++ b/yudao-module-haoka/yudao-module-haoka-biz/src/main/java/cn/iocoder/yudao/module/haoka/qetesh/JacksonHolder.java
@@ -0,0 +1,25 @@
+package cn.iocoder.yudao.module.haoka.qetesh;
+
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.module.paramnames.ParameterNamesModule;
+
+public class JacksonHolder {
+ public static final ObjectMapper objectMapper;
+
+
+ //init objectMapper
+ static {
+ objectMapper = new ObjectMapper();
+ objectMapper.registerModule(new ParameterNamesModule());
+ objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
+ }
+
+ public static String writeValueAsString(Object object) {
+ try {
+ return objectMapper.writeValueAsString(object);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+}
diff --git a/yudao-module-haoka/yudao-module-haoka-biz/src/main/java/cn/iocoder/yudao/module/haoka/qetesh/OpenapiAuthClient.java b/yudao-module-haoka/yudao-module-haoka-biz/src/main/java/cn/iocoder/yudao/module/haoka/qetesh/OpenapiAuthClient.java
new file mode 100644
index 0000000000..488c0164f7
--- /dev/null
+++ b/yudao-module-haoka/yudao-module-haoka-biz/src/main/java/cn/iocoder/yudao/module/haoka/qetesh/OpenapiAuthClient.java
@@ -0,0 +1,27 @@
+package cn.iocoder.yudao.module.haoka.qetesh;
+
+import feign.Headers;
+import feign.RequestLine;
+import lombok.Data;
+
+@Headers({
+ "Content-Type: application/json"
+})
+public interface OpenapiAuthClient {
+
+ @RequestLine("POST /oauth/v1/token")
+ ServiceResponse getToken(GetTokenRequest request);
+
+ @Data
+ class GetTokeResponse {
+ private String token;
+ private Integer timeExpire;
+ }
+
+ @Data
+ class GetTokenRequest {
+ private String appKey;
+
+ private String appSecret;
+ }
+}
diff --git a/yudao-module-haoka/yudao-module-haoka-biz/src/main/java/cn/iocoder/yudao/module/haoka/qetesh/OpenapiAuthClientConfig.java b/yudao-module-haoka/yudao-module-haoka-biz/src/main/java/cn/iocoder/yudao/module/haoka/qetesh/OpenapiAuthClientConfig.java
new file mode 100644
index 0000000000..5c5196731d
--- /dev/null
+++ b/yudao-module-haoka/yudao-module-haoka-biz/src/main/java/cn/iocoder/yudao/module/haoka/qetesh/OpenapiAuthClientConfig.java
@@ -0,0 +1,27 @@
+package cn.iocoder.yudao.module.haoka.qetesh;
+
+import feign.Feign;
+import feign.Logger.Level;
+import feign.Retryer;
+import feign.jackson.JacksonDecoder;
+import feign.jackson.JacksonEncoder;
+import feign.slf4j.Slf4jLogger;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class OpenapiAuthClientConfig {
+
+ @Bean
+ public OpenapiAuthClient openapiAuthClient(@Value("${openapi-demo.host}") String openapiHost) {
+ return Feign.builder()
+ .logger(new Slf4jLogger(OpenapiAuthClient.class))
+ .encoder(new JacksonEncoder())
+ .decoder(new JacksonDecoder())
+ .logLevel(Level.FULL)
+ .retryer(Retryer.NEVER_RETRY)
+ .target(OpenapiAuthClient.class, openapiHost);
+ }
+
+}
diff --git a/yudao-module-haoka/yudao-module-haoka-biz/src/main/java/cn/iocoder/yudao/module/haoka/qetesh/OpenapiClient.java b/yudao-module-haoka/yudao-module-haoka-biz/src/main/java/cn/iocoder/yudao/module/haoka/qetesh/OpenapiClient.java
new file mode 100644
index 0000000000..c238fae65c
--- /dev/null
+++ b/yudao-module-haoka/yudao-module-haoka-biz/src/main/java/cn/iocoder/yudao/module/haoka/qetesh/OpenapiClient.java
@@ -0,0 +1,409 @@
+package cn.iocoder.yudao.module.haoka.qetesh;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Lists;
+import feign.Headers;
+import feign.Param;
+import feign.QueryMap;
+import feign.RequestLine;
+import lombok.Data;
+import lombok.Value;
+
+import java.time.Instant;
+import java.time.LocalTime;
+import java.util.List;
+import java.util.Map;
+
+@Headers({
+ "Content-Type: application/json"
+})
+public interface OpenapiClient {
+
+ @RequestLine("POST /api/v1/speechskill/querySpeechSkillPage")
+ ServiceResponse> getSpeechSkillList(GetSpeechSkillListRequest request);
+
+ @Data
+ class GetSpeechSkillListRequest {
+
+ private int current = 1;
+
+ private int size = 10;
+
+ }
+
+ @RequestLine("GET /cti/queryCpnList")
+ ServiceResponse> getCpnList();
+
+ @Data
+ class GetCpnResponse {
+ //线路id
+ private Long id;
+ private String cpnCode;
+ private String contact;
+ private Integer concurrent;
+ private String explicitNumber;
+ private String limitBeginTime;
+ private String limitEndTime;
+ private String expirationTime;
+ private Integer useStatus;
+ private Long createTime;
+ private Integer cpnStatus;
+ private String prefix;
+ }
+
+ /**
+ * 创建普通任务
+ * @param request
+ * @return
+ */
+ @RequestLine("POST /outbound/tasks/temporary/fileless")
+ ServiceResponse createFilelessTask(CreateFilelessTaskRequest request);
+
+ /**
+ * 创建普通任务数据
+ * @param request
+ * @return
+ */
+ @RequestLine("POST /outbound/task/temporary/fileless/data")
+ ServiceResponse> createFilelessTaskData(CreateFilelessTaskDataRequest request);
+
+ /**
+ * 启动普通任务
+ * @param taskId
+ * @return
+ */
+ @RequestLine("PUT /outbound/task/temporary/fileless/{taskId}/start")
+ ServiceResponse> startFilelessTask(@Param("taskId") String taskId);
+
+ /**
+ * 更新普通任务
+ *
+ * @return
+ */
+ @RequestLine("PUT /outbound/tasks/temporary/fileless")
+ ServiceResponse> updateFilelessTask(UpdateFilelessTaskRequest request);
+
+ /**
+ * 更新任务状态
+ * @param request
+ * @return
+ */
+ @RequestLine("PUT /outbound/task/status")
+ ServiceResponse> updateTaskStatus(UpdateTaskStatusRequest request);
+
+ /**
+ * 创建长期任务
+ * @param request
+ * @return
+ */
+ @RequestLine("POST /outbound/tasks/permanent")
+ ServiceResponse createPermanentTask(CreatePermanentTaskRequest request);
+
+ /**
+ * 创建长期任务数据
+ * @param request
+ * @return
+ */
+ @RequestLine("POST /outbound/task/permanent/data")
+ ServiceResponse> createPermanentTaskData(CreatePermanentTaskDataRequest request);
+
+ /**
+ * 更新长期任务
+ * @param request
+ * @return
+ */
+ @RequestLine("PUT /outbound/tasks/permanent")
+ ServiceResponse> updatePermanentTask(UpdatePermanentTaskRequest request);
+
+ @RequestLine("GET /outbound/tasks")
+ ServiceResponse> queryTaskList(@QueryMap QueryTaskListRequest request);
+
+ @Data
+ class QueryTaskListRequest {
+ private String taskId;
+
+ private Long startTime;
+
+ private Long endTime;
+
+ private String taskName;
+
+ private List taskStatusList;
+
+ private String sortName;
+
+ private SortOrder sortOrder;
+
+ int pageIndex = 1;
+
+ int pageSize = 10;
+
+ public enum SortOrder {
+ ASC,DESC
+ }
+
+
+ }
+ @Data
+ class UpdatePermanentTaskRequest{
+ private String taskId;
+
+ /**
+ * 名称
+ */
+ private String name;
+
+ /**
+ * 工作时间
+ */
+ private WorkTime workTime;
+
+ /**
+ * 起止时间
+ */
+ private Life life;
+
+ private Boolean skipHolidays;
+ }
+
+ @Data
+ class CreatePermanentTaskDataRequest {
+
+ /**
+ * 任务id
+ */
+ private String taskId;
+
+ /**
+ * 载体
+ */
+ private List payloads;
+
+ /**
+ * 优先级 只支持0和1
+ */
+ private int priority = 0;
+
+ private Long speechSkillId;
+
+ private List lineIds;
+
+
+ }
+ @Data
+ class CreatePermanentTaskRequest {
+
+ /**
+ * 任务名称
+ */
+ private String name;
+
+ /**
+ * 起止设置
+ */
+ private Life life;
+
+ /**
+ * 工作时间设置
+ */
+ private WorkTime workTime;
+
+ }
+
+ @Data
+ class UpdateTaskStatusRequest {
+
+ /**
+ * 任务id
+ */
+ private String taskId;
+
+ /**
+ * 状态 2:允许 3:暂停 8:删除
+ */
+ private Integer status;
+ }
+ @Data
+ class UpdateFilelessTaskRequest {
+
+ private List lineIds;
+
+ private String taskId;
+
+ /**
+ * 起止时间
+ */
+ private Life life;
+
+ /**
+ * 工作时间
+ */
+ private WorkTime workTime;
+
+ private Boolean skipHolidays;
+
+ }
+
+ /**
+ * 任务的生命周期,何时开始,何时结束
+ */
+ @Value
+ class Life {
+
+ @JsonSerialize(using = CustomizeDatabind.InstantToLongSerializer.class)
+ Instant begin;
+
+ @JsonSerialize(using = CustomizeDatabind.InstantToLongSerializer.class)
+ Instant end;
+
+ @JsonCreator
+ public Life(
+ @JsonProperty("begin") @JsonDeserialize(using = CustomizeDatabind.LongToInstantDeserializer.class) Instant begin,
+ @JsonProperty("end") @JsonDeserialize(using = CustomizeDatabind.LongToInstantDeserializer.class) Instant end) {
+ if (!begin.isBefore(end)) {
+ throw new LifeNotValidExp();
+ }
+ this.begin = begin;
+ this.end = end;
+ }
+
+ public static Life forever() {
+ return new Life(Instant.EPOCH, Instant.ofEpochMilli(2147483647000L));
+ }
+
+ public static class LifeNotValidExp extends RuntimeException {
+
+ }
+ }
+
+ /**
+ * 工作时间段列表
+ */
+ @Value
+ class WorkTime {
+
+ List workHoursList;
+
+ @JsonCreator
+ public WorkTime(@JsonProperty("workHoursList") List workHoursList) {
+ this.workHoursList = workHoursList;
+ }
+
+
+ public static WorkTime allDay() {
+ WorkHours partOne = new WorkHours(LocalTime.MIN, LocalTime.NOON);
+ WorkHours partTwo = new WorkHours(LocalTime.NOON, LocalTime.MAX);
+ return new WorkTime(Lists.newArrayList(partOne, partTwo));
+ }
+
+ /**
+ * 一天中的一段时间
+ */
+ @Value
+ public static class WorkHours {
+
+ @JsonSerialize(using = CustomizeDatabind.LocalTimeToString.class)
+ LocalTime begin;
+
+ @JsonSerialize(using = CustomizeDatabind.LocalTimeToString.class)
+ LocalTime end;
+
+ @JsonCreator
+ public WorkHours(
+ @JsonProperty("begin") @JsonDeserialize(using = CustomizeDatabind.StringToLocalTime.class) LocalTime begin,
+ @JsonProperty("end") @JsonDeserialize(using = CustomizeDatabind.StringToLocalTime.class) LocalTime end) {
+ this.begin = begin;
+ this.end = end;
+ }
+ }
+ }
+
+ @Data
+ class RedialSetting {
+
+ /**
+ * 最大次数
+ */
+ Integer maxTimes;
+
+ /**
+ * 重播之间的间隔 单位ms
+ */
+ Long interval;
+
+ /**
+ * 需要重拨的结果类型
+ */
+ List results;
+ }
+
+ @Data
+ class CreateFilelessTaskRequest {
+
+ /**
+ * 任务名称,不要超过1024个字符
+ */
+ private String name;
+
+ /**
+ * 起止时间
+ */
+ private Life life;
+
+ /**
+ * 工作时间
+ */
+ private WorkTime workTime;
+
+ /**
+ * 话术id
+ */
+ private Long speechSkillId;//话术id
+
+ /**
+ * 重呼设置
+ */
+ private RedialSetting redialSetting;
+
+ /**
+ * 线路id列表
+ */
+ private List lineIds;
+
+ /**
+ * 跳过节假日
+ */
+ private Boolean skipHolidays;
+
+ }
+
+ @Value
+ class TaskDataPayload {
+ Map payload;
+
+ @JsonCreator
+ public TaskDataPayload(@JsonProperty("payload") Map payload) {
+ Preconditions.checkNotNull(payload);
+ this.payload = payload;
+ }
+ }
+
+ @Data
+ class CreateFilelessTaskDataRequest{
+ /**
+ * 任务id
+ */
+ private String taskId;
+
+ /**
+ * 数据列表
+ */
+ private List payloads;
+
+ }
+
+}
diff --git a/yudao-module-haoka/yudao-module-haoka-biz/src/main/java/cn/iocoder/yudao/module/haoka/qetesh/OpenapiClientConfig.java b/yudao-module-haoka/yudao-module-haoka-biz/src/main/java/cn/iocoder/yudao/module/haoka/qetesh/OpenapiClientConfig.java
new file mode 100644
index 0000000000..31a618731f
--- /dev/null
+++ b/yudao-module-haoka/yudao-module-haoka-biz/src/main/java/cn/iocoder/yudao/module/haoka/qetesh/OpenapiClientConfig.java
@@ -0,0 +1,30 @@
+package cn.iocoder.yudao.module.haoka.qetesh;
+
+import feign.Feign;
+import feign.Logger.Level;
+import feign.Retryer;
+import feign.jackson.JacksonDecoder;
+import feign.jackson.JacksonEncoder;
+import feign.slf4j.Slf4jLogger;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Slf4j
+@Configuration
+public class OpenapiClientConfig {
+
+ @Bean
+ public OpenapiClient openapiClient(@Value("${openapi-demo.host}") String openapiHost,
+ TokenRequestInterceptor tokenRequestInterceptor) {
+ return Feign.builder()
+ .logger(new Slf4jLogger(OpenapiClient.class))
+ .encoder(new JacksonEncoder())
+ .decoder(new JacksonDecoder())
+ .requestInterceptor(tokenRequestInterceptor)
+ .logLevel(Level.FULL)
+ .retryer(Retryer.NEVER_RETRY)
+ .target(OpenapiClient.class, openapiHost);
+ }
+}
diff --git a/yudao-module-haoka/yudao-module-haoka-biz/src/main/java/cn/iocoder/yudao/module/haoka/qetesh/ServiceResponse.java b/yudao-module-haoka/yudao-module-haoka-biz/src/main/java/cn/iocoder/yudao/module/haoka/qetesh/ServiceResponse.java
new file mode 100644
index 0000000000..6448032a06
--- /dev/null
+++ b/yudao-module-haoka/yudao-module-haoka-biz/src/main/java/cn/iocoder/yudao/module/haoka/qetesh/ServiceResponse.java
@@ -0,0 +1,54 @@
+package cn.iocoder.yudao.module.haoka.qetesh;
+
+public class ServiceResponse {
+ private int code;
+ private String msg;
+ private T data;
+
+
+ public int getCode() {
+ return this.code;
+ }
+
+ public ServiceResponse setCode(int code) {
+ this.code = code;
+ return this;
+ }
+
+ public String getMsg() {
+ return this.msg;
+ }
+
+ public ServiceResponse setMsg(String msg) {
+ this.msg = msg;
+ return this;
+ }
+
+ public T getData() {
+ return this.data;
+ }
+
+ public ServiceResponse setData(T data) {
+ this.data = data;
+ return this;
+ }
+
+
+
+ public ServiceResponse(int code, String msg, T data) {
+ this.code = code;
+ this.msg = msg;
+ this.data = data;
+ }
+
+ public ServiceResponse() {
+ }
+
+ public ServiceResponse(int code, String msg) {
+ this.code = code;
+ this.msg = msg;
+ }
+
+
+}
+
diff --git a/yudao-module-haoka/yudao-module-haoka-biz/src/main/java/cn/iocoder/yudao/module/haoka/qetesh/TokenRequestInterceptor.java b/yudao-module-haoka/yudao-module-haoka-biz/src/main/java/cn/iocoder/yudao/module/haoka/qetesh/TokenRequestInterceptor.java
new file mode 100644
index 0000000000..b62cfa0e24
--- /dev/null
+++ b/yudao-module-haoka/yudao-module-haoka-biz/src/main/java/cn/iocoder/yudao/module/haoka/qetesh/TokenRequestInterceptor.java
@@ -0,0 +1,40 @@
+package cn.iocoder.yudao.module.haoka.qetesh;
+
+//import com.kxjl.qeteshopenapidemo.OpenapiAuthClient.GetTokeResponse;
+//import com.kxjl.qeteshopenapidemo.OpenapiAuthClient.GetTokenRequest;
+import feign.RequestInterceptor;
+import feign.RequestTemplate;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+@Slf4j
+@Component
+public class TokenRequestInterceptor implements RequestInterceptor {
+
+ @Autowired
+ private OpenapiAuthClient openapiAuthClient;
+
+ @Value("${openapi-demo.appKey}")
+ private String appKey;
+
+ @Value("${openapi-demo.appSecret}")
+ private String appSecret;
+
+ @Override
+ public void apply(RequestTemplate template) {
+ if (template.request().url()
+ .contains("/oauth/v1/token")) {
+ return;
+ }
+ OpenapiAuthClient.GetTokenRequest request = new OpenapiAuthClient.GetTokenRequest();
+ request.setAppKey(appKey);
+ request.setAppSecret(appSecret);
+ ServiceResponse response = openapiAuthClient.getToken(request);
+ if (response.getCode() != 0) {
+ log.warn("获取token失败");
+ }
+ template.header("Authorization", "Bearer " + response.getData().getToken());
+ }
+}
diff --git a/yudao-module-haoka/yudao-module-haoka-biz/src/main/resources/lib/doudian-sdk-java-1.1.0.jar b/yudao-module-haoka/yudao-module-haoka-biz/src/main/resources/lib/doudian-sdk-java-1.1.0.jar
new file mode 100644
index 0000000000..f1c5a71df0
Binary files /dev/null and b/yudao-module-haoka/yudao-module-haoka-biz/src/main/resources/lib/doudian-sdk-java-1.1.0.jar differ
diff --git a/yudao-server/pom.xml b/yudao-server/pom.xml
index 429a7e55db..4565b1d42d 100644
--- a/yudao-server/pom.xml
+++ b/yudao-server/pom.xml
@@ -165,6 +165,9 @@
+
+ true
+
diff --git a/yudao-server/src/main/resources/application-dev.yaml b/yudao-server/src/main/resources/application-dev.yaml
index cd8652c79e..59d868c1e0 100644
--- a/yudao-server/src/main/resources/application-dev.yaml
+++ b/yudao-server/src/main/resources/application-dev.yaml
@@ -213,4 +213,8 @@ iot:
# 保持连接
keepalive: 60
# 清除会话(设置为false,断开连接,重连后使用原来的会话 保留订阅的主题,能接收离线期间的消息)
- clearSession: true
\ No newline at end of file
+ clearSession: true
+openapi-demo:
+ host: http://qetesh.kxjlcc.com:31880/qetesh-openapi
+ appKey: 0257a273c480433b85e141e61a5c6fe1
+ appSecret: $2a$10$0nARFdymExxJ9spsMsbyJeuzVKfmOMO0m6OoJsHOhgbxr4InimA9W
\ No newline at end of file
diff --git a/yudao-server/src/main/resources/application-local.yaml b/yudao-server/src/main/resources/application-local.yaml
index 409dff5a25..8de1fee17f 100644
--- a/yudao-server/src/main/resources/application-local.yaml
+++ b/yudao-server/src/main/resources/application-local.yaml
@@ -177,6 +177,8 @@ logging:
cn.iocoder.yudao.module.iot.dal.mysql: debug
cn.iocoder.yudao.module.ai.dal.mysql: debug
org.springframework.context.support.PostProcessorRegistrationDelegate: ERROR # TODO 芋艿:先禁用,Spring Boot 3.X 存在部分错误的 WARN 提示
+ cn.iocoder.yudao.module.haoka.qetesh.OpenapiAuthClient: debug
+ cn.iocoder.yudao.module.haoka.qetesh.OpenapiClient: debug
debug: false
@@ -273,3 +275,7 @@ iot:
keepalive: 60
# 清除会话(设置为false,断开连接,重连后使用原来的会话 保留订阅的主题,能接收离线期间的消息)
clearSession: true
+openapi-demo:
+ host: http://qetesh.kxjlcc.com:31880/qetesh-openapi
+ appKey: 0257a273c480433b85e141e61a5c6fe1
+ appSecret: $2a$10$0nARFdymExxJ9spsMsbyJeuzVKfmOMO0m6OoJsHOhgbxr4InimA9W
\ No newline at end of file
diff --git a/yudao-server/src/main/resources/application-staging.yaml b/yudao-server/src/main/resources/application-staging.yaml
index 8419cea706..28a03271ae 100644
--- a/yudao-server/src/main/resources/application-staging.yaml
+++ b/yudao-server/src/main/resources/application-staging.yaml
@@ -177,6 +177,8 @@ logging:
cn.iocoder.yudao.module.iot.dal.mysql: debug
cn.iocoder.yudao.module.ai.dal.mysql: debug
org.springframework.context.support.PostProcessorRegistrationDelegate: ERROR # TODO 芋艿:先禁用,Spring Boot 3.X 存在部分错误的 WARN 提示
+ cn.iocoder.yudao.module.haoka.qetesh.OpenapiAuthClient: debug
+ cn.iocoder.yudao.module.haoka.qetesh.OpenapiClient: debug
debug: false
@@ -273,3 +275,7 @@ iot:
keepalive: 60
# 清除会话(设置为false,断开连接,重连后使用原来的会话 保留订阅的主题,能接收离线期间的消息)
clearSession: true
+openapi-demo:
+ host: http://qetesh.kxjlcc.com:31880/qetesh-openapi
+ appKey: 0257a273c480433b85e141e61a5c6fe1
+ appSecret: $2a$10$0nARFdymExxJ9spsMsbyJeuzVKfmOMO0m6OoJsHOhgbxr4InimA9W
\ No newline at end of file
diff --git a/yudao-server/src/main/resources/application-test.yaml b/yudao-server/src/main/resources/application-test.yaml
index f162abceee..5a09ccd0a5 100644
--- a/yudao-server/src/main/resources/application-test.yaml
+++ b/yudao-server/src/main/resources/application-test.yaml
@@ -177,6 +177,8 @@ logging:
cn.iocoder.yudao.module.iot.dal.mysql: debug
cn.iocoder.yudao.module.ai.dal.mysql: debug
org.springframework.context.support.PostProcessorRegistrationDelegate: ERROR # TODO 芋艿:先禁用,Spring Boot 3.X 存在部分错误的 WARN 提示
+ cn.iocoder.yudao.module.haoka.qetesh.OpenapiAuthClient: debug
+ cn.iocoder.yudao.module.haoka.qetesh.OpenapiClient: debug
debug: false
@@ -273,3 +275,7 @@ iot:
keepalive: 60
# 清除会话(设置为false,断开连接,重连后使用原来的会话 保留订阅的主题,能接收离线期间的消息)
clearSession: true
+openapi-demo:
+ host: http://qetesh.kxjlcc.com:31880/qetesh-openapi
+ appKey: 0257a273c480433b85e141e61a5c6fe1
+ appSecret: $2a$10$0nARFdymExxJ9spsMsbyJeuzVKfmOMO0m6OoJsHOhgbxr4InimA9W
\ No newline at end of file