diff --git a/.idea/compiler.xml b/.idea/compiler.xml new file mode 100644 index 0000000..019b91a --- /dev/null +++ b/.idea/compiler.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/encodings.xml b/.idea/encodings.xml new file mode 100644 index 0000000..c0ed014 --- /dev/null +++ b/.idea/encodings.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/.idea/jarRepositories.xml b/.idea/jarRepositories.xml new file mode 100644 index 0000000..1067e4c --- /dev/null +++ b/.idea/jarRepositories.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/jpa-buddy.xml b/.idea/jpa-buddy.xml new file mode 100644 index 0000000..898e07a --- /dev/null +++ b/.idea/jpa-buddy.xml @@ -0,0 +1,7 @@ + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..2943e7c --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2023 OSSEZ.COM + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..f852fb5 --- /dev/null +++ b/README.md @@ -0,0 +1,112 @@ +# WeChat-Official-Account-Spring + +

+ + + +
This project builds by JDK 11 and OpenJ9 for JVM. +

+ +* [社区和讨论 (community)](https://www.ossez.com/tag/wechat) + +Spring Boot API Project for WeChat-J library. + +这是一个基于 WeChat-J 和 Spring Boot 的 API 微信公众号测试程序。 + +我们旨在提供一个初始化的开发框架,能够让应用在使用 Spring Boot 框架的基础上让你的微信公众号快速接入微信平台。 + +# 项目配置 + +和所有的 Java 项目的标准配置一样,你首先需要把依赖添加到你的项目中,然后完成属性文件配置。 + +在这个基础上,需要有一些先决条件。 + +## 先决条件 + +需要对微信公众号进行测试,你首先需要有一个微信公众号,如果没有的话,你可以使用微信提供的测试公众号来获得需要的 appID 和 +appsecret。 + +* [微信测试平台获得测试账号](https://www.ossez.com/t/topic/14281) + +## 依赖 + +项目使用的是 Maven,如果你只希望使用 WeChat-J,你只需要往你的项目中添加依赖即可。 + +因为我们目前还在对项目进行整理,所以还是使用的 SNAPSHOT 版本。 + +```xml + + + com.ossez.wechat + wechat-j-oa + 0.0.1-SNAPSHOT + +``` + +## 修改配置文件 + +```properties +# WeChat Official Cccount Conf +wechat.official-account.app-id=appId +wechat.official-account.secret=secret +wechat.official-account.token=token +wechat.official-account.aes-key=aesKey +# 存储配置redis(可选) +wx.mp.config-storage.type=Jedis # 配置类型: Memory(默认), Jedis, RedisTemplate +wx.mp.config-storage.key-prefix=wx # 相关redis前缀配置: wx(默认) +wx.mp.config-storage.redis.host=127.0.0.1 +wx.mp.config-storage.redis.port=6379 +#单机和sentinel同时存在时,优先使用sentinel配置 +#wx.mp.config-storage.redis.sentinel-ips=127.0.0.1:16379,127.0.0.1:26379 +#wx.mp.config-storage.redis.sentinel-name=mymaster +# http客户端配置 +wx.mp.config-storage.http-client-type=httpclient # http客户端类型: HttpClient(默认), OkHttp, JoddHttp +wx.mp.config-storage.http-proxy-host= +wx.mp.config-storage.http-proxy-port= +wx.mp.config-storage.http-proxy-username= +wx.mp.config-storage.http-proxy-password= +# 公众号地址host配置 +#wx.mp.hosts.api-host=http://proxy.com/ +#wx.mp.hosts.open-host=http://proxy.com/ +#wx.mp.hosts.mp-host=http://proxy.com/ +``` + +## 自动注入的类型 + +- `WxMpService` +- `WxMpConfigStorage` + +# 联系方式 + +请使用下面的联系方式和我们联系。 + +* [社区和讨论](https://www.ossez.com/tag/chat-gpt) + +| 联系方式名称 | 联系方式 | +|------------------|-----------------------------------------------| +| 电子邮件(Email) | [yhu@ossez.com](mailto:yhu@ossez.com) | +| QQ 或微信(WeChat) | 103899765 | +| QQ 交流群 | 15186112 | +| 社区论坛 (Community) | https://www.ossez.com/c/computer-technology/7 | + +# 公众平台 + +我们建议您通过社区论坛来和我们进行沟通,请关注我们公众平台上的账号 + +## 微信公众号 + +![](https://cdn.ossez.com/img/cwikius/cwikius-qr-wechat-search-w400.png) + +## 头条号 + +我们也在头条号上创建了我们的公众号,请扫描下面的 QR 关注我们的头条号。 + +![](https://cdn.ossez.com/img/cwikius/cwikus-qr-toutiao.png) + +## 知乎 + +请关注我们的知乎:https://www.zhihu.com/people/huyuchengus + +# License + +[WeChat-Official-Account-Spring is licensed under the MIT License](https://src.ossez.com/honeymoose/WeChat-Official-Account-Spring/src/branch/master/LICENSE) diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..0fd5b44 --- /dev/null +++ b/pom.xml @@ -0,0 +1,178 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 2.7.5 + + + com.ossez.openai + openai-spring + 0.0.1-SNAPSHOT + OpenAI- Spring Demo + OpenAI- Demo Example + + + The MIT license + https://opensource.org/licenses/mit-license.php + repo + + + + + YuCheng Hu + honeymoose + huyuchengus@gmail.com + -5 + Open Source + + Sr. Java Developer + + + + + + + com.ossez.wechat + wechat-j-oa + 0.0.1-SNAPSHOT + + + + + org.slf4j + slf4j-api + 1.7.36 + + + + org.projectlombok + lombok + 1.18.24 + provided + + + + redis.clients + jedis + compile + + + + + + org.springframework.boot + spring-boot-autoconfigure + + + org.springframework.boot + spring-boot-configuration-processor + true + + + org.springframework.boot + spring-boot-starter + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-data-redis + 3.0.1 + + + org.springframework.boot + spring-boot-starter-data-jpa + + + com.h2database + h2 + runtime + + + + + org.springframework.boot + spring-boot-starter-test + test + + + org.junit.jupiter + junit-jupiter + test + + + org.assertj + assertj-core + 3.24.1 + test + + + + + + + + + org.apache.maven.plugins + maven-deploy-plugin + 3.0.0 + + + default-deploy + deploy + + deploy + + + + + + + + + + org.apache.maven.plugins + maven-source-plugin + 3.2.1 + + + attach-sources + + jar-no-fork + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 3.4.1 + + 17 + + + + attach-javadocs + + jar + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.10.1 + + 17 + + + + + diff --git a/src/main/java/com/ossez/openai/demo/Application.java b/src/main/java/com/ossez/openai/demo/Application.java new file mode 100644 index 0000000..074d6ba --- /dev/null +++ b/src/main/java/com/ossez/openai/demo/Application.java @@ -0,0 +1,13 @@ +package com.ossez.openai.demo; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +@Slf4j +public class Application { + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } +} diff --git a/src/main/java/com/ossez/openai/demo/common/enums/HttpClientCategory.java b/src/main/java/com/ossez/openai/demo/common/enums/HttpClientCategory.java new file mode 100644 index 0000000..48c2fc4 --- /dev/null +++ b/src/main/java/com/ossez/openai/demo/common/enums/HttpClientCategory.java @@ -0,0 +1,12 @@ +package com.ossez.openai.demo.common.enums; + +/** + * User different http client to make api call. + * We should only keep OK_HTTP, this enough for package + * + * @author YuCheng Hu + */ +public enum HttpClientCategory { + OK_HTTP, HTTP_CLIENT + +} diff --git a/src/main/java/com/ossez/openai/demo/common/enums/StorageCategory.java b/src/main/java/com/ossez/openai/demo/common/enums/StorageCategory.java new file mode 100644 index 0000000..936ac21 --- /dev/null +++ b/src/main/java/com/ossez/openai/demo/common/enums/StorageCategory.java @@ -0,0 +1,13 @@ +package com.ossez.openai.demo.common.enums; + +/** + * WeChat's Storage Category + * + * We provide implement for MEM(RAM) and REDIS + * + * @author YuCheng Hu + */ +@Deprecated +public enum StorageCategory { + MEM, REDIS +} diff --git a/src/main/java/com/ossez/openai/demo/config/WeChatConfiguration.java b/src/main/java/com/ossez/openai/demo/config/WeChatConfiguration.java new file mode 100644 index 0000000..6585aef --- /dev/null +++ b/src/main/java/com/ossez/openai/demo/config/WeChatConfiguration.java @@ -0,0 +1,57 @@ +package com.ossez.openai.demo.config; + +import com.ossez.wechat.common.config.ConfigStorage; +import com.ossez.wechat.common.exception.WxErrorException; +import com.ossez.openai.demo.common.enums.HttpClientCategory; +import com.ossez.openai.demo.properties.WeChatOfficialAccountProperties; +import com.ossez.wechat.oa.api.WeChatOfficialAccountService; +import com.ossez.wechat.oa.api.impl.okhttp.WeChatPlatformService; +import com.ossez.wechat.oa.api.impl.okhttp.WeChatOfficialAccountServiceOkHttp; +import org.springframework.beans.factory.config.ConfigurableBeanFactory; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; +import org.springframework.context.annotation.Scope; + +/** + * . + * + * @author someone + */ +@Configuration +@EnableConfigurationProperties(WeChatOfficialAccountProperties.class) +@Import({WeChatStorageAutoConfiguration.class}) +public class WeChatConfiguration { + + + /** + * weChat Service Inject + */ + @Bean + @ConditionalOnMissingBean + public WeChatOfficialAccountService weChatOfficialAccountService(ConfigStorage configStorage, WeChatOfficialAccountProperties weChatOfficialAccountProperties) { + HttpClientCategory httpClientCategory = weChatOfficialAccountProperties.getWeChatDataStorage().getHttpClientCategory(); + WeChatOfficialAccountService weChatOfficialAccountService = new WeChatOfficialAccountServiceOkHttp(); + + weChatOfficialAccountService.setWxMpConfigStorage(configStorage); + return weChatOfficialAccountService; + } + + @Bean + @ConditionalOnMissingBean + @Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE) + public WeChatPlatformService weChatPlatformService(WeChatOfficialAccountService weChatOfficialAccountService) throws WxErrorException { + weChatOfficialAccountService.getAccessToken(); + return new WeChatPlatformService(weChatOfficialAccountService); + } +// +// @Bean +// @ConditionalOnMissingBean +// @Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE) +// public WeChatMsgService weChatMsgService(WeChatOfficialAccountService weChatOfficialAccountService) throws WxErrorException { +// return new WeChatMsgService(weChatOfficialAccountService); +// +// } +} diff --git a/src/main/java/com/ossez/openai/demo/config/WeChatStorageAutoConfiguration.java b/src/main/java/com/ossez/openai/demo/config/WeChatStorageAutoConfiguration.java new file mode 100644 index 0000000..df2cbdc --- /dev/null +++ b/src/main/java/com/ossez/openai/demo/config/WeChatStorageAutoConfiguration.java @@ -0,0 +1,109 @@ +package com.ossez.openai.demo.config; + +import com.ossez.wechat.common.config.ConfigStorage; +import com.ossez.openai.demo.common.enums.StorageCategory; +import com.ossez.openai.demo.model.entity.WeChatDataStorage; +import com.ossez.openai.demo.properties.WeChatOfficialAccountProperties; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import com.ossez.wechat.common.redis.RedisTemplateWxRedisOps; +import com.ossez.wechat.common.redis.WxRedisOps; +import com.ossez.wechat.common.config.WxMpHostConfig; +import com.ossez.wechat.common.config.DefaultConfigStorage; +import com.ossez.wechat.common.config.RedisConfigStorage; +import org.apache.commons.lang3.StringUtils; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.context.ApplicationContext; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.core.StringRedisTemplate; + +/** + * 微信公众号存储策略自动配置. + * + * @author Luo + */ +@Slf4j +@Configuration +@RequiredArgsConstructor +public class WeChatStorageAutoConfiguration { + private final ApplicationContext applicationContext; + + private final WeChatOfficialAccountProperties weChatOfficialAccountProperties; + + @Bean + @ConditionalOnMissingBean(ConfigStorage.class) + public ConfigStorage wxMpConfigStorage() { + StorageCategory type = weChatOfficialAccountProperties.getWeChatDataStorage().getType(); + ConfigStorage config; + switch (type) { + case REDIS: + config = redisTemplateConfigStorage(); + break; + default: + config = defaultConfigStorage(); + break; + } + // wx host config + if (null != weChatOfficialAccountProperties.getHosts() && StringUtils.isNotEmpty(weChatOfficialAccountProperties.getHosts().getApiHost())) { + WxMpHostConfig hostConfig = new WxMpHostConfig(); + hostConfig.setApiHost(weChatOfficialAccountProperties.getHosts().getApiHost()); + hostConfig.setMpHost(weChatOfficialAccountProperties.getHosts().getMpHost()); + hostConfig.setOpenHost(weChatOfficialAccountProperties.getHosts().getOpenHost()); + config.setHostConfig(hostConfig); + } + return config; + } + + private ConfigStorage defaultConfigStorage() { + DefaultConfigStorage config = new DefaultConfigStorage(); + configWeChatServer(config); + return config; + } + + + private ConfigStorage redisTemplateConfigStorage() { + StringRedisTemplate redisTemplate = null; + try { + redisTemplate = applicationContext.getBean(StringRedisTemplate.class); + } catch (Exception e) { + log.error(e.getMessage(), e); + } + try { + if (null == redisTemplate) { + redisTemplate = (StringRedisTemplate) applicationContext.getBean("stringRedisTemplate"); + } + } catch (Exception e) { + log.error(e.getMessage(), e); + } + + if (null == redisTemplate) { + redisTemplate = (StringRedisTemplate) applicationContext.getBean("redisTemplate"); + } + + WxRedisOps redisOps = new RedisTemplateWxRedisOps(redisTemplate); + RedisConfigStorage redisConfigStorage = new RedisConfigStorage(redisOps, + weChatOfficialAccountProperties.getWeChatDataStorage().getKeyPrefix()); + + configWeChatServer(redisConfigStorage); + return redisConfigStorage; + } + + private void configWeChatServer(DefaultConfigStorage defaultConfigStorage) { + WeChatOfficialAccountProperties properties = weChatOfficialAccountProperties; + WeChatDataStorage weChatDataStorage = weChatOfficialAccountProperties.getWeChatDataStorage(); + + defaultConfigStorage.setAppId(properties.getAppId()); + defaultConfigStorage.setSecret(properties.getSecret()); + defaultConfigStorage.setToken(properties.getToken()); + defaultConfigStorage.setAesKey(properties.getAesKey()); + + defaultConfigStorage.setHttpProxyHost(weChatDataStorage.getHttpProxyHost()); + defaultConfigStorage.setHttpProxyUsername(weChatDataStorage.getHttpProxyUsername()); + defaultConfigStorage.setHttpProxyPassword(weChatDataStorage.getHttpProxyPassword()); + if (weChatDataStorage.getHttpProxyPort() != null) { + defaultConfigStorage.setHttpProxyPort(weChatDataStorage.getHttpProxyPort()); + } + } + +} diff --git a/src/main/java/com/ossez/openai/demo/controller/OpenAIController.java b/src/main/java/com/ossez/openai/demo/controller/OpenAIController.java new file mode 100644 index 0000000..c0cf887 --- /dev/null +++ b/src/main/java/com/ossez/openai/demo/controller/OpenAIController.java @@ -0,0 +1,80 @@ +package com.ossez.openai.demo.controller; + +import com.ossez.wechat.common.exception.WxErrorException; +import com.ossez.wechat.common.model.res.QueryQuotaResponse; +import com.ossez.openai.demo.data.repository.redis.StudentRepository; +import com.ossez.openai.demo.service.OpenAIService; +import com.ossez.wechat.oa.api.WeChatOfficialAccountService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +/** + * WeChatController to process WeChat request + * + * @author YuCheng Hu + */ +@RestController +@RequestMapping(value = "/openai") +@Slf4j +public class OpenAIController { + + private final WeChatOfficialAccountService weChatOfficialAccountService; + private final OpenAIService openAIService; + private final StudentRepository studentRepository; + + @Autowired + public OpenAIController(WeChatOfficialAccountService weChatOfficialAccountService, OpenAIService openAIService, StudentRepository studentRepository) { + this.weChatOfficialAccountService = weChatOfficialAccountService; + this.openAIService = openAIService; + this.studentRepository = studentRepository; + } + + /** + * Get weChat access token + * + * @return The access token + * @throws WxErrorException WeChat API Error + */ + @GetMapping("/chat") + @ResponseBody + public String getAccessToken() throws WxErrorException { + log.debug("Get access token from WeChat"); + return weChatOfficialAccountService.getAccessToken(true); + } + + @GetMapping("/config") + @ResponseBody + public String getDomainIPs() throws WxErrorException { + log.debug("Get access token from WeChat"); + return openAIService.getDomainIPs(); + } + +// @GetMapping("/networkcheck") +// @ResponseBody +// public NetworkCheckResponse checkNetwork() throws WxErrorException { +// log.debug("Get access token from WeChat"); +// return weChatPlatformService.checkNetwork(); +// } +// + @PostMapping("/session") + @ResponseBody + public QueryQuotaResponse queryQuota() throws WxErrorException { + log.debug("Get access token from WeChat"); + return openAIService.queryQuota(); + } + @PostMapping("/verify") + @ResponseBody + public QueryQuotaResponse verify() throws WxErrorException { + log.debug("Get access token from WeChat"); + return openAIService.queryQuota(); + } + + @GetMapping("/message/send") + @ResponseBody + public String sendMessage() throws WxErrorException { + log.debug("Get access token from WeChat"); + return openAIService.sendMessage(); + } + +} diff --git a/src/main/java/com/ossez/openai/demo/data/repository/redis/StudentRepository.java b/src/main/java/com/ossez/openai/demo/data/repository/redis/StudentRepository.java new file mode 100644 index 0000000..350a869 --- /dev/null +++ b/src/main/java/com/ossez/openai/demo/data/repository/redis/StudentRepository.java @@ -0,0 +1,9 @@ +package com.ossez.openai.demo.data.repository.redis; + + +import com.ossez.openai.demo.model.entity.Student; +import org.springframework.data.repository.CrudRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface StudentRepository extends CrudRepository {} diff --git a/src/main/java/com/ossez/openai/demo/model/entity/Student.java b/src/main/java/com/ossez/openai/demo/model/entity/Student.java new file mode 100644 index 0000000..0fecbce --- /dev/null +++ b/src/main/java/com/ossez/openai/demo/model/entity/Student.java @@ -0,0 +1,62 @@ +package com.ossez.openai.demo.model.entity; + +import org.springframework.data.redis.core.RedisHash; + +import java.io.Serializable; + +@RedisHash("Student") +public class Student implements Serializable { + + public enum Gender { + MALE, FEMALE + } + + private String id; + private String name; + private Gender gender; + private int grade; + + public Student(String id, String name, Gender gender, int grade) { + this.id = id; + this.name = name; + this.gender = gender; + this.grade = grade; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Gender getGender() { + return gender; + } + + public void setGender(Gender gender) { + this.gender = gender; + } + + public int getGrade() { + return grade; + } + + public void setGrade(int grade) { + this.grade = grade; + } + + @Override + public String toString() { + return "Student{" + "id='" + id + '\'' + ", name='" + name + '\'' + ", gender=" + gender + ", grade=" + grade + '}'; + } +} \ No newline at end of file diff --git a/src/main/java/com/ossez/openai/demo/model/entity/WeChatDataStorage.java b/src/main/java/com/ossez/openai/demo/model/entity/WeChatDataStorage.java new file mode 100644 index 0000000..043783c --- /dev/null +++ b/src/main/java/com/ossez/openai/demo/model/entity/WeChatDataStorage.java @@ -0,0 +1,28 @@ +package com.ossez.openai.demo.model.entity; + +import com.ossez.openai.demo.common.enums.HttpClientCategory; +import com.ossez.openai.demo.common.enums.StorageCategory; +import com.ossez.openai.demo.properties.RedisProperties; +import lombok.Getter; +import lombok.Setter; +import lombok.experimental.Accessors; +import org.springframework.boot.context.properties.NestedConfigurationProperty; + +import java.io.Serializable; + +@Getter +@Setter +@Accessors(chain = true) +public class WeChatDataStorage implements Serializable { + private static final long serialVersionUID = -94405301936095366L; + private StorageCategory type = StorageCategory.MEM; + private String keyPrefix = "wx"; + @NestedConfigurationProperty + private final RedisProperties redis = new RedisProperties(); + private HttpClientCategory httpClientCategory = HttpClientCategory.OK_HTTP; + private String httpProxyHost; + private Integer httpProxyPort; + private String httpProxyUsername; + private String httpProxyPassword; + +} diff --git a/src/main/java/com/ossez/openai/demo/model/entity/WeChatHost.java b/src/main/java/com/ossez/openai/demo/model/entity/WeChatHost.java new file mode 100644 index 0000000..ce093eb --- /dev/null +++ b/src/main/java/com/ossez/openai/demo/model/entity/WeChatHost.java @@ -0,0 +1,16 @@ +package com.ossez.openai.demo.model.entity; + +import lombok.Data; +import lombok.experimental.Accessors; + +import java.io.Serializable; + +@Data +@Accessors(chain = true) +public class WeChatHost implements Serializable { + private static final long serialVersionUID = -7648920647310280817L; + private String apiHost; + private String openHost; + private String mpHost; + +} diff --git a/src/main/java/com/ossez/openai/demo/properties/RedisProperties.java b/src/main/java/com/ossez/openai/demo/properties/RedisProperties.java new file mode 100644 index 0000000..5eeff20 --- /dev/null +++ b/src/main/java/com/ossez/openai/demo/properties/RedisProperties.java @@ -0,0 +1,56 @@ +package com.ossez.openai.demo.properties; + +import lombok.Data; + +import java.io.Serializable; + +/** + * redis 配置属性. + * + * @author Binary Wang + * created on 2020-08-30 + */ +@Data +public class RedisProperties implements Serializable { + private static final long serialVersionUID = -5924815351660074401L; + + /** + * 主机地址. + */ + private String host = "127.0.0.1"; + + /** + * 端口号. + */ + private int port = 6379; + + /** + * 密码. + */ + private String password; + + /** + * 超时. + */ + private int timeout = 2000; + + /** + * 数据库. + */ + private int database = 0; + + /** + * sentinel ips + */ + private String sentinelIps; + + /** + * sentinel name + */ + private String sentinelName; + + private Integer maxActive; + private Integer maxIdle; + private Integer maxWaitMillis; + private Integer minIdle; +} diff --git a/src/main/java/com/ossez/openai/demo/properties/WeChatOfficialAccountProperties.java b/src/main/java/com/ossez/openai/demo/properties/WeChatOfficialAccountProperties.java new file mode 100644 index 0000000..b7a0600 --- /dev/null +++ b/src/main/java/com/ossez/openai/demo/properties/WeChatOfficialAccountProperties.java @@ -0,0 +1,25 @@ +package com.ossez.openai.demo.properties; + + +import com.ossez.openai.demo.model.entity.WeChatDataStorage; +import com.ossez.openai.demo.model.entity.WeChatHost; +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; + +/** + * WeChat Official Account Config + * + * @author YuCheng Hu + */ +@Data +@ConfigurationProperties(prefix = "wechat.official-account") +public class WeChatOfficialAccountProperties { + private String appId; //微信公众号 appId + private String secret; //微信公众号 secret + private String token; //微信公众号 token + private String aesKey; //微信公众号 aesKey + private WeChatHost hosts; //自定义 host 配置 + private final WeChatDataStorage weChatDataStorage = new WeChatDataStorage(); + + +} diff --git a/src/main/java/com/ossez/openai/demo/service/OpenAIService.java b/src/main/java/com/ossez/openai/demo/service/OpenAIService.java new file mode 100644 index 0000000..71393d6 --- /dev/null +++ b/src/main/java/com/ossez/openai/demo/service/OpenAIService.java @@ -0,0 +1,59 @@ +package com.ossez.openai.demo.service; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.ossez.wechat.common.exception.WxErrorException; +import com.ossez.wechat.common.model.req.CustomMessage; +import com.ossez.wechat.common.model.res.QueryQuotaResponse; +import com.ossez.wechat.oa.api.WeChatOfficialAccountService; +import com.ossez.wechat.oa.api.impl.okhttp.WeChatMsgService; +import com.ossez.wechat.oa.api.impl.okhttp.WeChatPlatformService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +/** + * Created with IntelliJ IDEA. + * + * @author XieYang, YuCheng + * @Date: 2022/10/14/16:17 + * @Description: + */ +@Service +@Slf4j +public class OpenAIService { + private final WeChatOfficialAccountService weChatOfficialAccountService; + private final ObjectMapper objectMapper; + + + @Autowired + public OpenAIService(WeChatOfficialAccountService weChatOfficialAccountService, ObjectMapper objectMapper) throws WxErrorException { + this.weChatOfficialAccountService = weChatOfficialAccountService; + this.objectMapper = objectMapper; + } + + + /** + * Get WeChatLoginQRUrl + * + * @return + */ + public String getDomainIPs() throws WxErrorException { + return new WeChatPlatformService(weChatOfficialAccountService).getDomainIPs(); + } + + public QueryQuotaResponse queryQuota() throws WxErrorException { + return new WeChatPlatformService(weChatOfficialAccountService).queryQuota(); + } + + public String sendMessage() throws WxErrorException { + CustomMessage.KfText kfText = new CustomMessage.KfText("微信异步消息发送"); + CustomMessage customMessage = new CustomMessage(); + customMessage.setToUser("o9phd5jz_We8mPs1ovmyjud97Ock"); + customMessage.setMsgType("text"); + customMessage.setText(kfText); + + return new WeChatMsgService(weChatOfficialAccountService).sendMessage(customMessage); + } + + +} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties new file mode 100644 index 0000000..627bd9e --- /dev/null +++ b/src/main/resources/application.properties @@ -0,0 +1,54 @@ +server.port=8080 + +spring.batch.job.enabled = false +spring.batch.jdbc.initialize-schema=ALWAYS + +logging.level.org.springframework=INFO +logging.level.root=DEBUG + +spring.jpa.show-sql=false +spring.jpa.hibernate.ddl-auto=none +spring.jpa.hibernate.use-new-id-generator-mappings=false + +#spring.datasource.driver-class-name=org.mariadb.jdbc.Driver +#spring.datasource.url= +#spring.datasource.username= +#spring.datasource.password= + +spring.datasource.url=jdbc:h2:mem:test +spring.datasource.driverClassName=org.h2.Driver +spring.datasource.username=sa +spring.datasource.password=password +spring.jpa.database-platform=org.hibernate.dialect.H2Dialect +spring.h2.console.enabled=true +spring.h2.console.path=/h2-console + +spring.datasource.hikari.connection-timeout=50000 +spring.datasource.hikari.idle-timeout=300000 +spring.datasource.hikari.max-lifetime=900000 +spring.datasource.hikari.maximum-pool-size=10 +spring.datasource.hikari.minimum-idle=10 +spring.datasource.hikari.pool-name=ConnPool +spring.datasource.hikari.connection-test-query=select 1 from dual + +spring.datasource.hikari.data-source-properties.cachePrepStmts=true +spring.datasource.hikari.data-source-properties.prepStmtCacheSize=250 +spring.datasource.hikari.data-source-properties.prepStmtCacheSqlLimit=2048 +spring.datasource.hikari.data-source-properties.useServerPrepStmts=true +spring.datasource.hikari.data-source-properties.useLocalSessionState=true +spring.datasource.hikari.data-source-properties.rewriteBatchedStatements=true +spring.datasource.hikari.data-source-properties.cacheResultSetMetadata=true +spring.datasource.hikari.data-source-properties.cacheServerConfiguration=true +spring.datasource.hikari.data-source-properties.elideSetAutoCommits=true +spring.datasource.hikari.data-source-properties.maintainTimeStats=false + +# REDIS +spring.redis.host=localhost +spring.redis.port=6379 + +# KEY +wechat.official-account.app-id = wx637b82a7f94123ef +wechat.official-account.secret = 343cecbc44d69e45367a65cc9b4d3925 +wechat.official-account.token = 0b01a700891d4a2f93a4323771c32455 +wechat.official-account.aes-key = aesKey + diff --git a/src/main/resources/data.sql b/src/main/resources/data.sql new file mode 100644 index 0000000..c502b4e --- /dev/null +++ b/src/main/resources/data.sql @@ -0,0 +1,3 @@ +INSERT INTO CITY VALUES (11, 'Delhi', 110001); +INSERT INTO CITY VALUES (12, 'Kanpur', 208001); +INSERT INTO CITY VALUES (13, 'Lucknow', 226001); \ No newline at end of file diff --git a/src/main/resources/logback.xml b/src/main/resources/logback.xml new file mode 100644 index 0000000..bd8ebdf --- /dev/null +++ b/src/main/resources/logback.xml @@ -0,0 +1,75 @@ + + + + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + %d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n + + + + + + + true + + + /var/log/usreio/%d{yyyy-MM-dd}/usreio-debug.log + + + 30 + 3GB + + + true + true + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + true + + ERROR + + + + /var/log/usreio/%d{yyyy-MM-dd}/usreio-error.log + + + 30 + 3GB + + + true + true + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/schema.sql b/src/main/resources/schema.sql new file mode 100644 index 0000000..ae0ef2b --- /dev/null +++ b/src/main/resources/schema.sql @@ -0,0 +1,7 @@ +DROP TABLE IF EXISTS CITY; +CREATE TABLE CITY +( + city_code INT AUTO_INCREMENT PRIMARY KEY, + city_name VARCHAR NOT NULL, + city_pincode INT NOT NULL +); \ No newline at end of file diff --git a/src/test/java/com/ossez/openai/demo/DataTest.java b/src/test/java/com/ossez/openai/demo/DataTest.java new file mode 100644 index 0000000..de14711 --- /dev/null +++ b/src/test/java/com/ossez/openai/demo/DataTest.java @@ -0,0 +1,52 @@ +package com.ossez.openai.demo; + +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.math.NumberUtils; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; + +import java.util.*; +import java.util.function.Function; +import java.util.stream.Collectors; + +/** + * Email Testing + * + * @author YuCheng + */ +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +@Slf4j +class DataTest { + + @Test + public void testStartAndEndDateTime() { + +// List reqIds = Arrays.asList(1, 2); +// List reqs = Arrays.asList(1); +// Map map1 = reqIds.stream().collect(Collectors.toMap(Function.identity(), item -> reqs.contains(item))); +// Map map2 = reqIds.stream().collect(Collectors.toMap(Function.identity(), reqs::contains)); +// +// log.debug("Map Size {}",11+20); +// +// log.debug("Map Size {}", map2); +// +// +// List shiftIds = Arrays.asList(1, 2); +// Map shiftIdMaps = new HashMap(); +// shiftIdMaps.put(1, Boolean.TRUE); +// List reponse = shiftIds.stream().filter(item -> shiftIdMaps.get(item) == Boolean.TRUE).collect(Collectors.toListbi()); +// log.debug("Map Size {}", reponse); +// +// log.debug("Map Size {}",map2); + + Double test = 0.1; +// Objects.nonNull(test) + + System.out.println( NumberUtils.DOUBLE_ZERO.equals(test)); + + } + + +} + + diff --git a/src/test/java/com/ossez/openai/demo/WeChatTest.java b/src/test/java/com/ossez/openai/demo/WeChatTest.java new file mode 100644 index 0000000..47d98d6 --- /dev/null +++ b/src/test/java/com/ossez/openai/demo/WeChatTest.java @@ -0,0 +1,68 @@ +package com.ossez.openai.demo; + + +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.math.NumberUtils; +import org.dom4j.Document; +import org.dom4j.DocumentException; +import org.dom4j.io.SAXReader; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; + +import java.nio.charset.StandardCharsets; + +/** + * Email Testing + * + * @author YuCheng + */ +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +@Slf4j +class WeChatTest { + + private String wechatMessageStr = StringUtils.EMPTY; + + @BeforeEach + protected void setUp() throws Exception { + this.wechatMessageStr = (" \n" + + " \n" + + " \n" + + " 1348831860\n" + + " \n" + + " \n" + + " 1234567890123456\n" + + " xxxx\n" + + " xxxx\n" + + ""); + + } + + @AfterEach + protected void tearDown() throws Exception { + } + + + @Test + public void testToWeChatMessage() { + SAXReader xmlReader = new SAXReader(); + Document document = null; + + + + try { + document = xmlReader.read(IOUtils.toInputStream(wechatMessageStr, StandardCharsets.UTF_8)); + + + + +// log.debug("WeChat Message Content - [{}]", weChatMessage.getContent()); + } catch (DocumentException e) { + throw new RuntimeException(e); + } + } +} + diff --git a/src/test/resources/application.properties b/src/test/resources/application.properties new file mode 100644 index 0000000..3e98aab --- /dev/null +++ b/src/test/resources/application.properties @@ -0,0 +1,42 @@ +server.port=8080 + +spring.batch.job.enabled = false +spring.batch.jdbc.initialize-schema=ALWAYS + +logging.level.org.springframework=INFO +logging.level.root=DEBUG + +spring.jpa.show-sql=false +spring.jpa.hibernate.ddl-auto=none +spring.jpa.hibernate.use-new-id-generator-mappings=false + +spring.datasource.driver-class-name=org.mariadb.jdbc.Driver +spring.datasource.url= +spring.datasource.username= +spring.datasource.password= + +spring.datasource.hikari.connection-timeout=50000 +spring.datasource.hikari.idle-timeout=300000 +spring.datasource.hikari.max-lifetime=900000 +spring.datasource.hikari.maximum-pool-size=10 +spring.datasource.hikari.minimum-idle=10 +spring.datasource.hikari.pool-name=ConnPool +spring.datasource.hikari.connection-test-query=select 1 from dual + +spring.datasource.hikari.data-source-properties.cachePrepStmts=true +spring.datasource.hikari.data-source-properties.prepStmtCacheSize=250 +spring.datasource.hikari.data-source-properties.prepStmtCacheSqlLimit=2048 +spring.datasource.hikari.data-source-properties.useServerPrepStmts=true +spring.datasource.hikari.data-source-properties.useLocalSessionState=true +spring.datasource.hikari.data-source-properties.rewriteBatchedStatements=true +spring.datasource.hikari.data-source-properties.cacheResultSetMetadata=true +spring.datasource.hikari.data-source-properties.cacheServerConfiguration=true +spring.datasource.hikari.data-source-properties.elideSetAutoCommits=true +spring.datasource.hikari.data-source-properties.maintainTimeStats=false + +# KEY +wechat.official-account.app-id = wx637b82a7f94123ef +wechat.official-account.secret = 343cecbc44d69e45367a65cc9b4d3925 +wechat.official-account.token = 0b01a700891d4a2f93a4323771c32455 +wechat.official-account.aes-key = aesKey + diff --git a/src/test/resources/logback.xml b/src/test/resources/logback.xml new file mode 100644 index 0000000..bd8ebdf --- /dev/null +++ b/src/test/resources/logback.xml @@ -0,0 +1,75 @@ + + + + + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + %d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n + + + + + + + true + + + /var/log/usreio/%d{yyyy-MM-dd}/usreio-debug.log + + + 30 + 3GB + + + true + true + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + true + + ERROR + + + + /var/log/usreio/%d{yyyy-MM-dd}/usreio-error.log + + + 30 + 3GB + + + true + true + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + + + + + + + + + + + \ No newline at end of file