作者 钟来

Default Changelist

... ... @@ -30,10 +30,12 @@ public class ChatGPTApiController {
@PostMapping("/sendFreeMessage")
public String sendFreeMessage(@RequestBody String jsonStr)
{
logger.info("请求内容:{}", jsonStr);
int timeout = 3000000;
Map<String,String> map = new HashMap<>();
map.put("Authorization","Bearer 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");
String str = HttpRequest.post("https://api.openai.com/v1/chat/completions").setReadTimeout(timeout).timeout(timeout).addHeaders(map).body(jsonStr).execute().body();
logger.info("返回内容:{}", str);
return str;
}
... ... @@ -41,10 +43,12 @@ public class ChatGPTApiController {
@PostMapping("/sendNotFreeMessage")
public String sendNotFreeMessage(@RequestBody String jsonStr)
{
logger.info("请求内容:{}", jsonStr);
int timeout = 3000000;
Map<String,String> map = new HashMap<>();
map.put("Authorization","Bearer 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");
String str = HttpRequest.post("https://api.openai.com/v1/chat/completions").setReadTimeout(timeout).timeout(timeout).addHeaders(map).body(jsonStr).execute().body();
logger.info("返回内容:{}", str);
return str;
}
... ...
... ... @@ -8,10 +8,7 @@ import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.Message;
import com.ruoyi.common.core.domain.MessageCode;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.utils.Arith;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.*;
import com.ruoyi.common.utils.bean.BeanUtils;
import com.ruoyi.system.login.dto.OpenAiLoginUser;
import com.ruoyi.system.login.dto.OpenAiUserInfo;
... ... @@ -243,12 +240,12 @@ public class ChatGPTController extends BaseController {
*/
private CompletionResult3_5 sendGPTAi(List<ChatRoomMessages> messageList)
{
logger.info("请求内容:{}",messageList);
logger.info("请求内容:{}",GsonConstructor.get().toJson(messageList));
JSONObject jsonObject = new JSONObject();
jsonObject.put("model","gpt-3.5-turbo-0301");
jsonObject.put("messages",messageList);
String str = HttpUtil.post("http://23.224.171.145:8086/chatGPTApi/sendNotFreeMessage",jsonObject.toString());
// String str = HttpUtil.post("https://free.chatgpt.njlaikun.com/v1/chat/completions",jsonObject.toString());
// String str = HttpUtil.post("http://23.224.171.145:8086/chatGPTApi/sendNotFreeMessage",jsonObject.toString());
String str = HttpUtil.post("https://free.chatgpt.njlaikun.com/v1/chat/completions",jsonObject.toString());
logger.info("返回的数据:{}",str);
CompletionResult3_5 completionResult = JSONObject.parseObject(str, CompletionResult3_5.class);
... ... @@ -262,12 +259,12 @@ public class ChatGPTController extends BaseController {
*/
private CompletionResult3_5 sendFreeGPTAi(List<ChatRoomMessages> messageList)
{
logger.info("请求内容:{}",messageList);
logger.info("请求内容:{}", GsonConstructor.get().toJson(messageList));
JSONObject jsonObject = new JSONObject();
jsonObject.put("model","gpt-3.5-turbo-0301");
jsonObject.put("messages",messageList);
String str = HttpUtil.post("https://23.224.171.145:8086/chatGPTApi/sendFreeMessage",jsonObject.toString());
// String str = HttpUtil.post("https://free.chatgpt.njlaikun.com/v1/chat/completions",jsonObject.toString());
// String str = HttpUtil.post("http://23.224.171.145:8086/chatGPTApi/sendFreeMessage",jsonObject.toString());
String str = HttpUtil.post("https://free.chatgpt.njlaikun.com/v1/chat/completions",jsonObject.toString());
logger.info("返回的数据:{}",str);
CompletionResult3_5 completionResult = JSONObject.parseObject(str, CompletionResult3_5.class);
... ...
... ... @@ -46,7 +46,7 @@ public class OpenAiUserLoginController extends BaseController {
@ApiImplicitParam(value = "验证码",name = "code"),
})
@PostMapping("/userpassLogin")
public AjaxResult userpassLogin(String code, String key)
public AjaxResult userpassLogin(String code, String key,String promo_code)
{
//验证验证码
String str = HttpUtil.post("http://ly.userlogin.yu2le.com/userLogin/verificationCode?key="+key+"&code="+code,new HashMap<>());
... ...
package com.zhonglai.luhui.openai.controller;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.Validator;
import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.file.FileUploadUtils;
import com.ruoyi.common.utils.file.FileUtils;
... ... @@ -11,17 +14,19 @@ import com.ruoyi.framework.config.ServerConfig;
import com.ruoyi.system.login.dto.OpenAiLoginUser;
import com.ruoyi.system.login.dto.OpenAiUserInfo;
import com.ruoyi.system.service.PublicService;
import com.zhonglai.luhui.openai.dto.CompletionChoiceMessage3_5;
import com.zhonglai.luhui.openai.dto.UserFlowPacketRemainLog;
import com.zhonglai.luhui.openai.service.VipServiceImpl;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
... ... @@ -37,6 +42,9 @@ public class UserInfoController extends BaseController {
@Autowired
private PublicService publicService;
@Autowired
private VipServiceImpl vipService;
@ApiOperation("获取用户信息")
@GetMapping("/getUserInfo")
public AjaxResult getUserInfo()
... ... @@ -84,7 +92,7 @@ public class UserInfoController extends BaseController {
public TableDataInfo useFlowPacketRemainLog()
{
startPage();
List<Map<String,Object>> list = publicService.getObjectListBySQL("SELECT * FROM `lk_openai`.`user_flow_packet_remain_log` WHERE `user_id`="+getUserId().intValue()+" and `type`=2 order by create_time desc");
List<Map<String,Object>> list = publicService.getObjectListBySQL("SELECT * FROM `lk_openai`.`user_flow_packet_remain_log` WHERE `user_id`="+getUserId().intValue()+" and (`type`=2 or `type`=3) order by create_time desc");
return getDataTable(list);
}
... ... @@ -137,4 +145,127 @@ public class UserInfoController extends BaseController {
return AjaxResult.error(e.getMessage());
}
}
@ApiOperation("代币代充")
@ApiImplicitParams({
@ApiImplicitParam(value = "需要充值的手机号",name = "phone"),
@ApiImplicitParam(value = "充值代币数量",name = "number")
})
@Transactional
@PostMapping("/agencyCharge/{phone}/{number}")
public AjaxResult agencyCharge(@PathVariable String phone,@PathVariable Long number)
{
if(!Validator.isMobile(phone))
{
return AjaxResult.error("请输入正确的手机号");
}
if(null == number || number<=0)
{
return AjaxResult.error("充值代币数量不合法");
}
List<Map<String,Object>> userList = publicService.getObjectListBySQL("SELECT * FROM `lk_openai`.`user_info` WHERE phone='"+phone+"'");
if(null == userList || userList.size()==0)
{
return AjaxResult.error("用户没有登陆,请提现用户使用手机号登陆以后,再充值");
}
OpenAiUserInfo myOpenAiUserInfo = publicService.getObjectForTableName(OpenAiUserInfo.class,"id",getUserId().toString(),"`lk_openai`.`user_info`");
if(myOpenAiUserInfo.getFlow_packet_remain()-number<=0)
{
return AjaxResult.error("您的余额不足请先为您自己充值");
}
if(myOpenAiUserInfo.getRole()-1!=0)
{
return AjaxResult.error("您不是代理商请先升级成代理商");
}
BigDecimal[] bs = vipService.getUnitprice();
BigDecimal openaiUnitprice = bs[0];
BigDecimal realityUnitprice = bs[1];
if(openaiUnitprice.doubleValue()==0 || realityUnitprice.doubleValue()==0)
{
return AjaxResult.error("系统未配置流量单价,请联系管理员");
}
//减去自己的余额
publicService.updateBySql("UPDATE `lk_openai`.`user_info` SET flow_packet_remain=flow_packet_remain-"+number+" WHERE id="+myOpenAiUserInfo.getId());
UserFlowPacketRemainLog userFlowPacketRemainLog = new UserFlowPacketRemainLog();
userFlowPacketRemainLog.setCreate_time(DateUtils.getNowTimeMilly());
userFlowPacketRemainLog.setUser_id(myOpenAiUserInfo.getId());
userFlowPacketRemainLog.setType(3); //消费
StringBuffer stringBuffer = new StringBuffer();
stringBuffer.append("为手机号:");
stringBuffer.append(phone);
stringBuffer.append(" 的用户代充:");
stringBuffer.append(number);
stringBuffer.append(" 代币");
stringBuffer.append(";");
stringBuffer.append("剩余代币: ");
stringBuffer.append(myOpenAiUserInfo.getFlow_packet_remain()-number);
stringBuffer.append(" ;");
userFlowPacketRemainLog.setDescribe(stringBuffer.toString());
userFlowPacketRemainLog.setTotal_tokens(number);
userFlowPacketRemainLog.setOpenai_money((openaiUnitprice.multiply(new BigDecimal(userFlowPacketRemainLog.getTotal_tokens()))).divide(new BigDecimal(1000),6,BigDecimal.ROUND_HALF_UP));
userFlowPacketRemainLog.setReality_money((realityUnitprice.multiply(new BigDecimal(userFlowPacketRemainLog.getTotal_tokens()))).divide(new BigDecimal(1000),6,BigDecimal.ROUND_HALF_UP));
publicService.insertToTable(userFlowPacketRemainLog,"`lk_openai`.`user_flow_packet_remain_log`");
OpenAiUserInfo openAiUserInfo = BeanUtil.mapToBean(userList.get(0),OpenAiUserInfo.class,null);
//添加客户的余额,和总额
publicService.updateBySql("UPDATE `lk_openai`.`user_info` SET flow_packet_remain=flow_packet_remain+"+number+",flow_packet_total=flow_packet_total+"+number+" WHERE id="+openAiUserInfo.getId());
userFlowPacketRemainLog = new UserFlowPacketRemainLog();
userFlowPacketRemainLog.setCreate_time(DateUtils.getNowTimeMilly());
userFlowPacketRemainLog.setUser_id(openAiUserInfo.getId());
userFlowPacketRemainLog.setType(3); //消费
stringBuffer = new StringBuffer();
stringBuffer.append("代理商");
stringBuffer.append(myOpenAiUserInfo.getNickname());
stringBuffer.append("手机号:");
stringBuffer.append(myOpenAiUserInfo.getPhone());
stringBuffer.append(" 为您充值代币: ");
stringBuffer.append(number);
stringBuffer.append(" ;");
userFlowPacketRemainLog.setDescribe(stringBuffer.toString());
userFlowPacketRemainLog.setTotal_tokens(number);
userFlowPacketRemainLog.setOpenai_money((openaiUnitprice.multiply(new BigDecimal(userFlowPacketRemainLog.getTotal_tokens()))).divide(new BigDecimal(1000),6,BigDecimal.ROUND_HALF_UP));
userFlowPacketRemainLog.setReality_money((realityUnitprice.multiply(new BigDecimal(userFlowPacketRemainLog.getTotal_tokens()))).divide(new BigDecimal(1000),6,BigDecimal.ROUND_HALF_UP));
publicService.insertToTable(userFlowPacketRemainLog,"`lk_openai`.`user_flow_packet_remain_log`");
return AjaxResult.success("充值成功!");
}
@ApiOperation("升级为代理商")
@ApiImplicitParams({
@ApiImplicitParam(value = "推荐码",name = "promo_code"),
})
@Transactional
@PostMapping("/agencyCharge/{promo_code}")
public AjaxResult agencyCharge(@PathVariable String promo_code)
{
OpenAiUserInfo myOpenAiUserInfo = publicService.getObjectForTableName(OpenAiUserInfo.class,"id",getUserId().toString(),"`lk_openai`.`user_info`");
if(myOpenAiUserInfo.getRole()-1==0)
{
return AjaxResult.error("您已经是代理商,无法重复申请");
}
OpenAiUserInfo pOpenAiUserInfo = publicService.getObjectForTableName(OpenAiUserInfo.class,"promo_code",promo_code,"`lk_openai`.`user_info`");
if(null == pOpenAiUserInfo || pOpenAiUserInfo.getRole()-1!=0 || pOpenAiUserInfo.getState()==0 ||pOpenAiUserInfo.getState()==2)
{
return AjaxResult.error("该代理商不存在或者已被禁止");
}
OpenAiUserInfo upadduser = new OpenAiUserInfo();
upadduser.setId(myOpenAiUserInfo.getId());
upadduser.setPromo_code(Integer.toHexString((myOpenAiUserInfo.getId()+":"+DateUtils.getNowTimeMilly()).hashCode()).toUpperCase());
upadduser.setRole(1);
upadduser.setPid(pOpenAiUserInfo.getId());
return AjaxResult.success(publicService.updateObjectByTable(upadduser,"id","`lk_openai`.`user_info`"));
}
}
... ...
... ... @@ -10,7 +10,7 @@ public class UserFlowPacketRemainLog {
private BigDecimal openai_money; //bigint(20) DEFAULT NULL COMMENT 'openai费用(美元)',
private BigDecimal reality_money; //bigint(20) DEFAULT NULL COMMENT '实际费用(人民币)'
private String describe; //描述
private Integer type; //int(11) DEFAULT NULL COMMENT '类型(1充值,2消费)',
private Integer type; //int(11) DEFAULT NULL COMMENT '类型(1充值,2消费,3代充)',
public Integer getType() {
return type;
... ...
... ... @@ -34,6 +34,7 @@ public class ChatgptDetailsServiceImpl implements UserDetailsService {
adduser.setFlow_packet_total(10000);
adduser.setState(1);
publicService.insertToTable(adduser,"`lk_openai`.`user_info`");
log.info("新增用户{},成功",username);
openAiUserInfo = adduser;
}
... ...
# 项目相关配置 jhlt: # 名称 name: zhonglai # 版本 version: 3.8.2 # 版权年份 copyrightYear: 2022 # 获取ip地址开关 addressEnabled: false # 开发环境配置 server: # 服务器的HTTP端口,默认为8080 port: 8082 servlet: # 应用的访问路径 context-path: / tomcat: # tomcat的URI编码 uri-encoding: UTF-8 # 连接数满后的排队数,默认为100 accept-count: 1000 threads: # tomcat最大线程数,默认为200 max: 800 # Tomcat启动初始化的线程数,默认值10 min-spare: 100 # 日志配置 logging: level: com.ruoyi: debug org.springframework: warn # Spring配置 spring: # 资源信息 messages: # 国际化资源文件路径 basename: i18n/messages profiles: active: druid # 文件上传 servlet: multipart: # 单个文件大小 max-file-size: 10MB # 设置总上传的文件大小 max-request-size: 20MB # 服务模块 devtools: restart: # 热部署开关 enabled: true # redis 配置 redis: # 地址 host: 47.112.163.61 # 端口,默认为6379 port: 9527 # 数据库索引 database: 1 # 密码 password: Luhui586 # 连接超时时间 timeout: 10s lettuce: pool: # 连接池中的最小空闲连接 min-idle: 0 # 连接池中的最大空闲连接 max-idle: 8 # 连接池的最大数据库连接数 max-active: 8 # #连接池最大阻塞等待时间(使用负值表示没有限制) max-wait: -1ms # token配置 token: # 令牌自定义标识 header: Authorization # 令牌密钥 secret: abcdefghijklmnopqrstuvwxyz # 令牌有效期(默认30分钟) expireTime: 1440 rediskey: lh-openai # MyBatis配置 mybatis: # 搜索指定包别名 typeAliasesPackage: com.ruoyi.**.domain # 配置mapper的扫描,找到所有的mapper.xml映射文件 mapperLocations: classpath*:mapper/**/*Mapper.xml # 加载全局的配置文件 configLocation: classpath:mybatis/mybatis-config.xml # PageHelper分页插件 pagehelper: helperDialect: mysql supportMethodsArguments: true params: count=countSql # Swagger配置 swagger: # 是否开启swagger enabled: true # 请求前缀 pathMapping: /dev-api # 防止XSS攻击 xss: # 过滤开关 enabled: true # 排除链接(多个用逗号分隔) excludes: /system/notice # 匹配链接 urlPatterns: /system/*,/monitor/*,/tool/* mqtt: client: device_life: 180 # NameServer地址 rocketmq: name-server: 47.115.144.179:9876 # 默认的消息组 producer: group: deviceCommand send-message-timeout: 30000 send-topic: lh-chat-gpt send-tags: 1 sys: ## // 对于登录login 注册register 验证码captchaImage 允许匿名访问 antMatchers: /login,/register,/captchaImage,/getCacheObject,/v2/api-docs,/openAiUserLogin/*,/chatGPTStream/upUserFlowPacketRemain chatgpt: token: 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 timeout: 5000
\ No newline at end of file
# 项目相关配置 jhlt: # 名称 name: zhonglai # 版本 version: 3.8.2 # 版权年份 copyrightYear: 2022 # 获取ip地址开关 addressEnabled: false profile: D:/ruoyi/uploadPath # 开发环境配置 server: # 服务器的HTTP端口,默认为8080 port: 8082 servlet: # 应用的访问路径 context-path: / tomcat: # tomcat的URI编码 uri-encoding: UTF-8 # 连接数满后的排队数,默认为100 accept-count: 1000 threads: # tomcat最大线程数,默认为200 max: 800 # Tomcat启动初始化的线程数,默认值10 min-spare: 100 # 日志配置 logging: level: com.ruoyi: debug org.springframework: warn # Spring配置 spring: # 资源信息 messages: # 国际化资源文件路径 basename: i18n/messages profiles: active: druid # 文件上传 servlet: multipart: # 单个文件大小 max-file-size: 10MB # 设置总上传的文件大小 max-request-size: 20MB # 服务模块 devtools: restart: # 热部署开关 enabled: true # redis 配置 redis: # 地址 host: 47.112.163.61 # 端口,默认为6379 port: 9527 # 数据库索引 database: 1 # 密码 password: Luhui586 # 连接超时时间 timeout: 10s lettuce: pool: # 连接池中的最小空闲连接 min-idle: 0 # 连接池中的最大空闲连接 max-idle: 8 # 连接池的最大数据库连接数 max-active: 8 # #连接池最大阻塞等待时间(使用负值表示没有限制) max-wait: -1ms # token配置 token: # 令牌自定义标识 header: Authorization # 令牌密钥 secret: abcdefghijklmnopqrstuvwxyz # 令牌有效期(默认30分钟) expireTime: 1440 rediskey: lh-openai # MyBatis配置 mybatis: # 搜索指定包别名 typeAliasesPackage: com.ruoyi.**.domain # 配置mapper的扫描,找到所有的mapper.xml映射文件 mapperLocations: classpath*:mapper/**/*Mapper.xml # 加载全局的配置文件 configLocation: classpath:mybatis/mybatis-config.xml # PageHelper分页插件 pagehelper: helperDialect: mysql supportMethodsArguments: true params: count=countSql # Swagger配置 swagger: # 是否开启swagger enabled: true # 请求前缀 pathMapping: /dev-api # 防止XSS攻击 xss: # 过滤开关 enabled: true # 排除链接(多个用逗号分隔) excludes: /system/notice # 匹配链接 urlPatterns: /system/*,/monitor/*,/tool/* mqtt: client: device_life: 180 # NameServer地址 rocketmq: name-server: 47.115.144.179:9876 # 默认的消息组 producer: group: deviceCommand send-message-timeout: 30000 send-topic: lh-chat-gpt send-tags: 1 sys: ## // 对于登录login 注册register 验证码captchaImage 允许匿名访问 antMatchers: /login,/register,/captchaImage,/getCacheObject,/v2/api-docs,/openAiUserLogin/*,/chatGPTStream/upUserFlowPacketRemain chatgpt: token: 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 timeout: 5000
\ No newline at end of file
... ...
... ... @@ -6,8 +6,11 @@ import org.springframework.data.redis.core.BoundSetOperations;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.data.redis.core.script.RedisScript;
import org.springframework.stereotype.Component;
import java.time.Duration;
import java.util.*;
import java.util.concurrent.TimeUnit;
... ... @@ -256,4 +259,27 @@ public class RedisCache
Map<String, String> map = JSONObject.parseObject(s,HashMap.class);
setCacheMap(key, map);
}
//分布式锁过期时间 s 可以根据业务自己调节
private static final Long LOCK_REDIS_TIMEOUT = 10L;
//分布式锁休眠 至 再次尝试获取 的等待时间 ms 可以根据业务自己调节
public static final Long LOCK_REDIS_WAIT = 500L;
/**
* 加锁
**/
public Boolean getLock(String key,String value){
Boolean lockStatus = this.redisTemplate.opsForValue().setIfAbsent(key,value, Duration.ofSeconds(LOCK_REDIS_TIMEOUT));
return lockStatus;
}
/**
* 释放锁
**/
public Long releaseLock(String key,String value){
String luaScript = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
RedisScript<Long> redisScript = new DefaultRedisScript<>(luaScript,Long.class);
Long releaseStatus = (Long)this.redisTemplate.execute(redisScript, Collections.singletonList(key),value);
return releaseStatus;
}
}
... ...
... ... @@ -4,6 +4,7 @@ package com.ruoyi.system.login.dto;
import com.ruoyi.system.domain.tool.PublicSQLConfig;
import java.io.Serializable;
import java.math.BigDecimal;
/**
* 用户信息
... ... @@ -21,6 +22,51 @@ public class OpenAiUserInfo implements Serializable {
private Integer flow_packet_remain; //流量包余额
private Integer flow_packet_total; //流量包总额
private Integer state; //状态(0禁用,1正常,2过期,3锁定)
private Integer role; //角色(0普通用户,1代理商)
private Integer pid; //上级id
private BigDecimal unitprice; //流量单价
private BigDecimal default_below_unitprice; //默认下级流量单价
private String promo_code; //推广码
public String getPromo_code() {
return promo_code;
}
public void setPromo_code(String promo_code) {
this.promo_code = promo_code;
}
public Integer getRole() {
return role;
}
public void setRole(Integer role) {
this.role = role;
}
public Integer getPid() {
return pid;
}
public void setPid(Integer pid) {
this.pid = pid;
}
public BigDecimal getUnitprice() {
return unitprice;
}
public void setUnitprice(BigDecimal unitprice) {
this.unitprice = unitprice;
}
public BigDecimal getDefault_below_unitprice() {
return default_below_unitprice;
}
public void setDefault_below_unitprice(BigDecimal default_below_unitprice) {
this.default_below_unitprice = default_below_unitprice;
}
public Integer getState() {
return state;
... ...