初始版本提交
This commit is contained in:
commit
1f0bec8fb2
|
@ -0,0 +1,26 @@
|
|||
pipeline {
|
||||
agent {
|
||||
label 'test20'
|
||||
}
|
||||
|
||||
stages {
|
||||
stage('build') {
|
||||
steps {
|
||||
sh '''
|
||||
source /etc/profile
|
||||
mvn clean package -Dmaven.test.skip=true -U
|
||||
'''
|
||||
}
|
||||
}
|
||||
|
||||
stage('deploy') {
|
||||
steps {
|
||||
sh '''
|
||||
source /etc/profile
|
||||
cp -f fifa-api/target/fifa-api-1.1-SNAPSHOT.jar /data/upload/fifa-maker-api/
|
||||
sh /data/upload/fifa-maker-api/build.sh
|
||||
'''
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,180 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<groupId>com.alive</groupId>
|
||||
<artifactId>alive-api-server</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>alive-api</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<properties>
|
||||
<java.version>1.8</java.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.alive</groupId>
|
||||
<artifactId>alive-db</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<!-- 阿里云 OSS SDK 依赖 -->
|
||||
<dependency>
|
||||
<groupId>com.aliyun.oss</groupId>
|
||||
<artifactId>aliyun-sdk-oss</artifactId>
|
||||
<version>3.13.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.bouncycastle</groupId>
|
||||
<artifactId>bcprov-jdk15on</artifactId>
|
||||
<version>1.69</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.bitcoinj</groupId>
|
||||
<artifactId>bitcoinj-core</artifactId>
|
||||
<version>0.15.9</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.alive</groupId>
|
||||
<artifactId>alive-commons</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>mysql</groupId>
|
||||
<artifactId>mysql-connector-java</artifactId>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.web3j</groupId>
|
||||
<artifactId>core</artifactId>
|
||||
<version>5.0.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.squareup.okhttp3</groupId>
|
||||
<artifactId>okhttp</artifactId>
|
||||
<version>4.3.1</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>oauth.signpost</groupId>
|
||||
<artifactId>signpost-core</artifactId>
|
||||
<version>1.2.1.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>oauth.signpost</groupId>
|
||||
<artifactId>signpost-commonshttp4</artifactId>
|
||||
<version>1.2.1.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.twitter</groupId>
|
||||
<artifactId>twitter-api-java-sdk</artifactId>
|
||||
<version>1.1.4</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>commons-httpclient</groupId>
|
||||
<artifactId>commons-httpclient</artifactId>
|
||||
<version>3.1</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
<version>29.0-jre</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.bitcoinj</groupId>
|
||||
<artifactId>bitcoinj-core</artifactId>
|
||||
<version>0.15.5</version>
|
||||
</dependency>
|
||||
|
||||
<!-- TG 依赖 -->
|
||||
<dependency>
|
||||
<groupId>org.telegram</groupId>
|
||||
<artifactId>telegrambots</artifactId>
|
||||
<version>6.0.1</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
<dependency>
|
||||
<groupId>org.codehaus.groovy</groupId>
|
||||
<artifactId>groovy</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
<artifactId>gson</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mybatis</groupId>
|
||||
<artifactId>mybatis</artifactId>
|
||||
<version>3.5.9</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.xmlbeans</groupId>
|
||||
<artifactId>xmlbeans</artifactId>
|
||||
<version>3.1.0</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.codehaus.gmavenplus</groupId>
|
||||
<artifactId>gmavenplus-plugin</artifactId>
|
||||
<version>1.13.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>addSources</goal>
|
||||
<goal>addTestSources</goal>
|
||||
<goal>generateStubs</goal>
|
||||
<goal>compile</goal>
|
||||
<goal>generateTestStubs</goal>
|
||||
<goal>compileTests</goal>
|
||||
<goal>removeStubs</goal>
|
||||
<goal>removeTestStubs</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
|
@ -0,0 +1,17 @@
|
|||
package com.alive.server;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||
|
||||
@Slf4j
|
||||
@SpringBootApplication(scanBasePackages = "com.alive")
|
||||
@EnableScheduling
|
||||
public class AliveApiApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(AliveApiApplication.class, args);
|
||||
log.info("--------------ALIVE项目启动完成11-------------------");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
package com.alive.server;
|
||||
|
||||
import com.alive.server.service.TelegramServer;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.jooq.DSLContext;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.CommandLineRunner;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.telegram.telegrambots.meta.TelegramBotsApi;
|
||||
import org.telegram.telegrambots.meta.exceptions.TelegramApiException;
|
||||
import org.telegram.telegrambots.updatesreceivers.DefaultBotSession;
|
||||
|
||||
|
||||
@Order(2) //通过order注解指定执行顺序
|
||||
@Component
|
||||
@Slf4j
|
||||
public class BotRunnerInit implements CommandLineRunner {
|
||||
|
||||
@Autowired
|
||||
private DSLContext dslContext;
|
||||
|
||||
@Value("${com.alive.task.bot}")
|
||||
private Boolean taskBot;
|
||||
|
||||
@Override
|
||||
public void run(String... args){
|
||||
/*if(!taskBot){
|
||||
return;
|
||||
}
|
||||
TelegramBotsApi botsApi = null;
|
||||
try {
|
||||
botsApi = new TelegramBotsApi(DefaultBotSession.class);
|
||||
botsApi.registerBot(new TelegramServer(dslContext));
|
||||
} catch (TelegramApiException e) {
|
||||
log.error("TG连接网络异常-------err:{}",e.getMessage());
|
||||
}*/
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
package com.alive.server;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.cors.CorsConfiguration;
|
||||
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
|
||||
import org.springframework.web.filter.CorsFilter;
|
||||
|
||||
/**
|
||||
* 实现基本的跨域请求
|
||||
* @author linhongcun
|
||||
*
|
||||
*/
|
||||
@Configuration
|
||||
public class CorsConfig {
|
||||
|
||||
@Bean
|
||||
public CorsFilter corsFilter() {
|
||||
final UrlBasedCorsConfigurationSource urlBasedCorsConfigurationSource = new UrlBasedCorsConfigurationSource();
|
||||
final CorsConfiguration corsConfiguration = new CorsConfiguration();
|
||||
/*是否允许请求带有验证信息*/
|
||||
corsConfiguration.setAllowCredentials(true);
|
||||
/*允许访问的客户端域名*/
|
||||
corsConfiguration.addAllowedOrigin("*");
|
||||
/*允许服务端访问的客户端请求头*/
|
||||
corsConfiguration.addAllowedHeader("*");
|
||||
/*允许访问的方法名,GET POST等*/
|
||||
corsConfiguration.addAllowedMethod("*");
|
||||
urlBasedCorsConfigurationSource.registerCorsConfiguration("/**", corsConfiguration);
|
||||
return new CorsFilter(urlBasedCorsConfigurationSource);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,252 @@
|
|||
package com.alive.server.api;
|
||||
|
||||
import com.alive.commons.util.*;
|
||||
import com.alive.server.api.account.AccountSignInReq;
|
||||
import com.alive.server.api.account.AccountSignInResp;
|
||||
import com.alive.server.api.account.AccountSignUpReq;
|
||||
import com.alive.server.api.account.InviteReq;
|
||||
import com.alive.server.service.MemberService;
|
||||
import com.alive.server.service.WalletService;
|
||||
import com.alive.commons.annotation.Login;
|
||||
import com.alive.db.entity.Vo.UserVo;
|
||||
import com.alive.db.jooq.tables.pojos.TMemberPojo;
|
||||
import com.alive.db.jooq.tables.records.ActivityLogRecord;
|
||||
import com.alive.db.jooq.tables.records.TMemberRecord;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang.RandomStringUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.jooq.DSLContext;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.transaction.annotation.Isolation;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.sql.Timestamp;
|
||||
import java.util.*;
|
||||
|
||||
import static com.alive.db.jooq.Tables.*;
|
||||
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequestMapping("/api/account")
|
||||
@Api(tags = "账号相关")
|
||||
@Transactional(isolation = Isolation.READ_COMMITTED)
|
||||
@CrossOrigin(origins = "*")
|
||||
public class AccountController {
|
||||
|
||||
@Autowired
|
||||
private DSLContext dslContext;
|
||||
|
||||
@Autowired
|
||||
private MemberService memberService;
|
||||
|
||||
@Autowired
|
||||
private WalletService walletService;
|
||||
|
||||
@GetMapping("randomCode")
|
||||
@ApiOperation("获取钱包签名串")
|
||||
public UserVo randomCode(String account) {
|
||||
Assert.isTrue(!StringUtils.isBlank(account), "Account not null");
|
||||
account = account.trim().toLowerCase();
|
||||
UserVo userVo = new UserVo();
|
||||
String sin = NumberUtil.getUUIDBy16()+"PASSWORD";
|
||||
userVo.setEncryptedString(sin);
|
||||
RedisUtil.setEx(account,sin,60L);
|
||||
return userVo;
|
||||
}
|
||||
|
||||
@GetMapping("exist")
|
||||
@ApiOperation("检查账号是否注册")
|
||||
public Map<String, Boolean> exist(String account,Integer chainType) {
|
||||
Assert.isTrue(!StringUtils.isBlank(account), "Account not null");
|
||||
Assert.isTrue(chainType != null, "Chain not null");
|
||||
int count = dslContext.selectCount().from(T_MEMBER)
|
||||
.where(T_MEMBER.FLAG.eq((byte) 1).and(T_MEMBER.ACCOUNT.eq(account.toLowerCase().trim())))
|
||||
.fetchAnyInto(Integer.class);
|
||||
return Collections.singletonMap("exist", count > 0);
|
||||
}
|
||||
|
||||
@PostMapping("signUp")
|
||||
@ApiOperation("注册")
|
||||
public void signUp(@RequestBody @Validated AccountSignUpReq req) {
|
||||
req.setAccount(req.getAccount().trim().toLowerCase());
|
||||
Assert.isTrue(RedisUtil.tryLock("AccountController.signUp." + req.getAccount(), 3), "operate too frequently");
|
||||
log.info(">>> 新用户注册 - {}", JsonUtil.toJson(req));
|
||||
|
||||
int count = dslContext.selectCount().from(T_MEMBER)
|
||||
.where(T_MEMBER.FLAG.eq((byte) 1).and(T_MEMBER.ACCOUNT.eq(req.getAccount())))
|
||||
.fetchAnyInto(Integer.class);
|
||||
Assert.isTrue(count == 0, "Account Exist");
|
||||
|
||||
if (req.getShareCode() == null || req.getShareCode().trim().isEmpty()) {
|
||||
req.setShareCode("0");
|
||||
}
|
||||
TMemberPojo referMember = null;
|
||||
if(req.getShareCode() != null && !req.getShareCode().equals("0")){
|
||||
referMember = dslContext.select().from(T_MEMBER)
|
||||
.where(T_MEMBER.FLAG.eq((byte) 1).and(T_MEMBER.SHARE_CODE.eq(req.getShareCode().toUpperCase())))
|
||||
.fetchAnyInto(TMemberPojo.class);
|
||||
Assert.notNull(referMember, "Invalid Share Code");
|
||||
}
|
||||
if(referMember == null){
|
||||
referMember = new TMemberPojo();
|
||||
referMember.setId(0);
|
||||
referMember.setAllPid(",");
|
||||
}
|
||||
|
||||
//邀请码
|
||||
String shareCode = RandomStringUtils.random(6, true, true).toUpperCase(Locale.ROOT);
|
||||
while (true) {
|
||||
Integer tmp = dslContext.selectCount().from(T_MEMBER)
|
||||
.where(T_MEMBER.SHARE_CODE.eq(shareCode))
|
||||
.fetchAnyInto(Integer.class);
|
||||
if (tmp == 0) {
|
||||
break;
|
||||
}
|
||||
shareCode = RandomStringUtils.random(6, true, true).toUpperCase(Locale.ROOT);
|
||||
}
|
||||
|
||||
//UID
|
||||
String uid = "1" + RandomStringUtils.random(7, false, true).toUpperCase(Locale.ROOT);
|
||||
while (true) {
|
||||
Integer tmp = dslContext.selectCount().from(T_MEMBER)
|
||||
.where(T_MEMBER.UID.eq(uid))
|
||||
.fetchAnyInto(Integer.class);
|
||||
if (tmp == 0) {
|
||||
break;
|
||||
}
|
||||
uid = "1" + RandomStringUtils.random(7, false, true).toUpperCase(Locale.ROOT);
|
||||
}
|
||||
TMemberRecord memberRecord = dslContext.newRecord(T_MEMBER);
|
||||
memberRecord.setAccount(req.getAccount());
|
||||
memberRecord.setPasswordPay("");
|
||||
memberRecord.setPasswordLogin(Md5Util.encryptPassword(req.getPublicKey()));
|
||||
memberRecord.setReferId(referMember.getId());
|
||||
memberRecord.setChainType(req.getChainType());
|
||||
memberRecord.setUid(uid);
|
||||
memberRecord.setShareCode(shareCode);
|
||||
memberRecord.store();
|
||||
|
||||
memberRecord.setAllPid(referMember.getAllPid() + memberRecord.getId() + ",");
|
||||
memberRecord.store();
|
||||
walletService.initWallet(memberRecord.getId(),req.getAccount());
|
||||
|
||||
if(!referMember.getId().equals(0)){
|
||||
//更新团队
|
||||
List<Integer> allPids = memberService.splitAllPid(memberRecord.getAllPid());
|
||||
dslContext.update(T_MEMBER)
|
||||
.set(T_MEMBER.TEAM_NUM, T_MEMBER.TEAM_NUM.add(1))
|
||||
.where(T_MEMBER.ID.in(allPids)).execute();
|
||||
dslContext.update(T_MEMBER)
|
||||
.set(T_MEMBER.SHARE_NUM, T_MEMBER.SHARE_NUM.add(1))
|
||||
.where(T_MEMBER.ID.eq(referMember.getId())).execute();
|
||||
}else{
|
||||
dslContext.update(T_MEMBER)
|
||||
.set(T_MEMBER.TEAM_NUM, T_MEMBER.TEAM_NUM.add(1))
|
||||
.where(T_MEMBER.ID.in(memberRecord.getId())).execute();
|
||||
}
|
||||
}
|
||||
|
||||
@PostMapping("signIn")
|
||||
@ApiOperation("登录")
|
||||
public AccountSignInResp signIn(@RequestBody @Validated AccountSignInReq req) {
|
||||
req.setAccount(req.getAccount().trim().toLowerCase());
|
||||
TMemberRecord memberRecord = dslContext.selectFrom(T_MEMBER)
|
||||
.where(T_MEMBER.FLAG.eq((byte) 1)
|
||||
.and(T_MEMBER.ACCOUNT.eq(req.getAccount()))).fetchAny();
|
||||
|
||||
////todo 提示语国际化
|
||||
Assert.notNull(memberRecord, "Account Not Exist");
|
||||
String code = RedisUtil.get(req.getAccount());
|
||||
Assert.notNull(code, "signature error");
|
||||
|
||||
Assert.isTrue(req.getAccount() == null || EcRecoverUtil.checkEcRecover(code, req.getPassword(), req.getAccount()), "Bad Signature");
|
||||
|
||||
String redisKey = "iNode:loginToken:" + memberRecord.getId();
|
||||
String token = RedisUtil.get(redisKey);
|
||||
if (token == null) {
|
||||
token = JwtUtil.createJwtToken(memberRecord.getId().toString(), req.getAccount(), 86400L * 730L);
|
||||
//30s 内的重复登录,返回同一个token
|
||||
RedisUtil.setEx(redisKey, token, 30);
|
||||
}
|
||||
//校验一下是否有统计表
|
||||
walletService.verifyActivityStatisticsRecord(memberRecord.getAccount());
|
||||
AccountSignInResp resp = new AccountSignInResp();
|
||||
resp.setToken(token);
|
||||
return resp;
|
||||
}
|
||||
|
||||
@Login
|
||||
@PostMapping("bindingRelationship")
|
||||
@ApiOperation("绑定邀请关系")
|
||||
public Map<String,Boolean> bindingRelationship(@RequestBody @Validated InviteReq req){
|
||||
Map<String,Boolean> map = new HashMap<>();
|
||||
Integer memberId = Integer.parseInt(RequestUtil.getCurrentAccount());
|
||||
//邀请人
|
||||
TMemberPojo referMember = dslContext.select().from(T_MEMBER)
|
||||
.where(T_MEMBER.FLAG.eq((byte) 1).and(T_MEMBER.SHARE_CODE.eq(req.getShareCode().toUpperCase())))
|
||||
.fetchAnyInto(TMemberPojo.class);
|
||||
Assert.notNull(referMember, "Invalid Share Code");
|
||||
TMemberRecord tMemberRecord = memberService.fetchOne(memberId);
|
||||
Assert.isTrue(tMemberRecord.getReferId().equals(0), "Non repeatable binding");
|
||||
Assert.isTrue(!memberId.equals(referMember.getId()), "You can't invite yourself");
|
||||
tMemberRecord.setReferId(referMember.getId());
|
||||
tMemberRecord.setAllPid(referMember.getAllPid() + memberId + ",");
|
||||
tMemberRecord.store();
|
||||
|
||||
//查出我的全部下级人数、包含自己
|
||||
Integer countNumber = memberService.findTMemberRecordCount(memberId);
|
||||
|
||||
//更新团队
|
||||
List<Integer> allPids = memberService.splitAllPid(referMember.getAllPid());
|
||||
dslContext.update(T_MEMBER)
|
||||
.set(T_MEMBER.TEAM_NUM, T_MEMBER.TEAM_NUM.add(countNumber))
|
||||
.where(T_MEMBER.ID.in(allPids)).execute();
|
||||
|
||||
dslContext.update(T_MEMBER)
|
||||
.set(T_MEMBER.SHARE_NUM, T_MEMBER.SHARE_NUM.add(1))
|
||||
.where(T_MEMBER.ID.eq(referMember.getId())).execute();
|
||||
|
||||
//开始判断有没有做任务
|
||||
ActivityLogRecord activityLog = dslContext.selectFrom(ACTIVITY_LOG)
|
||||
.where(ACTIVITY_LOG.ADDRESS.eq(tMemberRecord.getAccount())
|
||||
.and(ACTIVITY_LOG.CONFIG_TYPE.eq(9).and(ACTIVITY_LOG.TYPE.eq(1)))).fetchAny();
|
||||
if(activityLog != null){
|
||||
activityLog.setType(2);
|
||||
activityLog.setEndTime(new Timestamp(System.currentTimeMillis()));
|
||||
activityLog.store();
|
||||
//开始增加奖励统计
|
||||
dslContext.update(ACTIVITY_STATISTICS).set(ACTIVITY_STATISTICS.AMOUNT,ACTIVITY_STATISTICS.AMOUNT.add(activityLog.getAmount())).where(ACTIVITY_STATISTICS.ADDRESS.eq(activityLog.getAddress())).execute();
|
||||
dslContext.update(ACTIVITY_STATISTICS).set(ACTIVITY_STATISTICS.AMOUNT,ACTIVITY_STATISTICS.AMOUNT.add(activityLog.getSuperiorAmount())).where(ACTIVITY_STATISTICS.ADDRESS.eq(activityLog.getSuperiorAddress())).execute();
|
||||
}
|
||||
map.put("result",tMemberRecord.getReferId().equals(0) ? false : true);
|
||||
return map;
|
||||
}
|
||||
|
||||
|
||||
@Login
|
||||
@GetMapping("bindOrNot")
|
||||
@ApiOperation("查询用户是否绑定关系")
|
||||
public Map<String,Boolean> bindOrNot(){
|
||||
Map<String,Boolean> map = new HashMap<>();
|
||||
int memberId = Integer.parseInt(RequestUtil.getCurrentAccount());
|
||||
TMemberRecord tMemberRecord = memberService.fetchOne(memberId);
|
||||
map.put("result",tMemberRecord.getReferId().equals(0) ? false : true);
|
||||
return map;
|
||||
}
|
||||
|
||||
private static byte[] hexToByteArray(String s) {
|
||||
int len = s.length();
|
||||
byte[] data = new byte[len / 2];
|
||||
for (int i = 0; i < len; i += 2) {
|
||||
data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
|
||||
+ Character.digit(s.charAt(i+1), 16));
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
package com.alive.server.api;
|
||||
|
||||
import com.alive.server.api.account.ActivityReq;
|
||||
import com.alive.server.api.account.ActivityTaskReq;
|
||||
import com.alive.server.api.account.UserInviteReq;
|
||||
import com.alive.commons.annotation.Login;
|
||||
import com.alive.commons.model.BasePageReq;
|
||||
import com.alive.db.entity.Vo.ActivityOutcomeVo;
|
||||
import com.alive.db.entity.Vo.ActivityTaskVo;
|
||||
import com.alive.db.entity.Vo.InviteCountVo;
|
||||
import com.alive.db.entity.Vo.RankingSummaryVo;
|
||||
import com.alive.server.service.ActivityService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequestMapping("/api/activity")
|
||||
@Api(tags = "活动相关")
|
||||
@CrossOrigin(origins = "*")
|
||||
public class ActivityController {
|
||||
|
||||
@Autowired
|
||||
private ActivityService activityService;
|
||||
|
||||
@GetMapping("findActivityList")
|
||||
@ApiOperation("查询活动列表")
|
||||
public ActivityOutcomeVo findActivityList(ActivityReq activityReq) {
|
||||
ActivityOutcomeVo activityOutcomeVo = new ActivityOutcomeVo();
|
||||
activityReq.setType(activityReq.getType() == null ? 1 : activityReq.getType());
|
||||
activityReq.setAddress(!StringUtils.isBlank(activityReq.getAddress()) ? activityReq.getAddress().toLowerCase() : null);
|
||||
activityOutcomeVo.setActivityConfigVos(activityService.findActivityList(activityReq));
|
||||
activityService.countActivity(activityOutcomeVo,activityReq);
|
||||
return activityOutcomeVo;
|
||||
}
|
||||
|
||||
@Login
|
||||
@PostMapping("startTheTask")
|
||||
@ApiOperation("开始活动任务")
|
||||
public ActivityTaskVo startTheTask(@RequestBody @Validated ActivityTaskReq activityTaskReq) {
|
||||
ActivityTaskVo activityOutcomeVo = new ActivityTaskVo();
|
||||
activityTaskReq.setAddress(!StringUtils.isBlank(activityTaskReq.getAddress()) ? activityTaskReq.getAddress().toLowerCase() : null);
|
||||
activityService.startTheTask(activityOutcomeVo,activityTaskReq);
|
||||
return activityOutcomeVo;
|
||||
}
|
||||
|
||||
|
||||
@Login
|
||||
@GetMapping("invitation")
|
||||
@ApiOperation("邀请页面")
|
||||
public InviteCountVo invitation(UserInviteReq userInviteReq) {
|
||||
InviteCountVo activityOutcomeVo = new InviteCountVo();
|
||||
Assert.notNull(userInviteReq.getAddress(), "address is null");
|
||||
userInviteReq.setAddress(!StringUtils.isBlank(userInviteReq.getAddress()) ? userInviteReq.getAddress().toLowerCase() : null);
|
||||
activityService.invitation(activityOutcomeVo,userInviteReq.getAddress());
|
||||
return activityOutcomeVo;
|
||||
}
|
||||
|
||||
|
||||
@GetMapping("ranking")
|
||||
@ApiOperation("排行榜")
|
||||
public RankingSummaryVo ranking(BasePageReq req, UserInviteReq userInviteReq) {
|
||||
userInviteReq.setAddress(!StringUtils.isBlank(userInviteReq.getAddress()) ? userInviteReq.getAddress().toLowerCase() : null);
|
||||
return activityService.ranking(req,userInviteReq);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,87 @@
|
|||
package com.alive.server.api;
|
||||
|
||||
import com.alive.commons.annotation.Login;
|
||||
import com.alive.commons.model.BasePageReq;
|
||||
import com.alive.db.entity.Vo.*;
|
||||
import com.alive.db.jooq.tables.records.CoinConfigRecord;
|
||||
import com.alive.server.api.account.AccountSignInReq;
|
||||
import com.alive.server.api.account.PayCoinReq;
|
||||
import com.alive.server.api.account.PayNodeSmsReq;
|
||||
import com.alive.server.api.account.TeskReq;
|
||||
import com.alive.server.service.CrowdfundingService;
|
||||
import com.alive.server.service.PersonalCenterService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.transaction.annotation.Isolation;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 众筹
|
||||
*
|
||||
* @author HayDen
|
||||
* @date 2024-05-24
|
||||
*/
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequestMapping("/api/crowdfunding")
|
||||
@Api(tags = "私募")
|
||||
@Transactional(isolation = Isolation.READ_COMMITTED)
|
||||
public class CrowdfundingController
|
||||
{
|
||||
@Autowired
|
||||
private CrowdfundingService crowdfundingService;
|
||||
|
||||
@GetMapping("contractAddress")
|
||||
@ApiOperation("获取合约地址")
|
||||
public Map<String,String> contractAddress(){
|
||||
Map<String,String> map = new HashMap<>();
|
||||
String address = crowdfundingService.contractAddress();
|
||||
map.put("address",address);
|
||||
return map;
|
||||
}
|
||||
|
||||
@GetMapping("getPrivatePlacement")
|
||||
@ApiOperation("查询私募信息")
|
||||
public PrivatePlacementVo getPrivatePlacement(){
|
||||
return crowdfundingService.getPrivatePlacement();
|
||||
}
|
||||
|
||||
@Login
|
||||
@PostMapping("payOrder")
|
||||
@ApiOperation("下单支付")
|
||||
public PayCoinVo payOrder(@RequestBody @Validated PayCoinReq req){
|
||||
return crowdfundingService.payOrder(req);
|
||||
}
|
||||
|
||||
@Login
|
||||
@PostMapping("claimTheAirdrop")
|
||||
@ApiOperation("领取空投")
|
||||
public Map<String,String> claimTheAirdrop(){
|
||||
return crowdfundingService.claimTheAirdrop();
|
||||
}
|
||||
|
||||
@GetMapping("getAirdropNumber")
|
||||
@ApiOperation("查询可领取空投数量")
|
||||
public Map<String,String> getAirdropNumber(){
|
||||
Map<String,String> map = new HashMap<>();
|
||||
map.put("result",crowdfundingService.getAirdropNumber());
|
||||
return map;
|
||||
}
|
||||
|
||||
@Login
|
||||
@GetMapping("pay_private_placement")
|
||||
@ApiOperation("支付通知")
|
||||
public NoticeOfPaymentVo payPrivatePlacement(@Validated PayNodeSmsReq req){
|
||||
NoticeOfPaymentVo vo = new NoticeOfPaymentVo();
|
||||
Boolean result = crowdfundingService.payNodeSms(req);
|
||||
return vo.setType(result ? 1 : 0);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
package com.alive.server.api;
|
||||
|
||||
import com.alive.commons.config.BaseComponent;
|
||||
import com.alive.commons.util.IntegerUtil;
|
||||
import com.alive.commons.util.RedisUtil;
|
||||
import com.alive.server.config.DiscordConfig;
|
||||
import com.alive.server.dto.UserDto;
|
||||
import com.alive.server.service.DiscordService;
|
||||
import com.alive.server.service.MemberService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.transaction.annotation.Isolation;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.web.bind.annotation.CrossOrigin;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequestMapping("/api/discord")
|
||||
@Api(tags = "discord服务")
|
||||
@Transactional(isolation = Isolation.READ_COMMITTED)
|
||||
@CrossOrigin(origins = "*")
|
||||
public class DiscordController extends BaseComponent {
|
||||
|
||||
@Autowired
|
||||
private DiscordService discordService;
|
||||
|
||||
@Autowired
|
||||
private MemberService memberService;
|
||||
|
||||
/**
|
||||
* 授权回调地址
|
||||
* @param code
|
||||
* @param state
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("authorizationCallbacksToken")
|
||||
@ApiOperation("授权回调地址")
|
||||
public Map<String,Boolean> authorizationCallbacksToken(String code,String state) {
|
||||
//防止用户频繁请求授权
|
||||
String key = "AUTHORIZATIONCALLBACKSTOKEN"+state;
|
||||
Integer value = IntegerUtil.getInteger(RedisUtil.get(key),0);
|
||||
value = value + 1;
|
||||
//防止用户频繁请求授权
|
||||
RedisUtil.setEx(key,value.toString(),60 * 3);
|
||||
|
||||
Map<String,Boolean> map = new HashMap<>();
|
||||
try {
|
||||
state = state.toLowerCase();
|
||||
//根据code换取token
|
||||
discordService.getTokenByCode(code,state);
|
||||
if(memberService.countDiscordUser(state) != 0){
|
||||
UserDto userDto = discordService.findUser(state);
|
||||
//判断Discord是否已绑定
|
||||
discordService.bindUser(userDto.getId());
|
||||
memberService.renewalUserDiscord(state,userDto.getId());
|
||||
}
|
||||
map.put("result",true);
|
||||
}catch (Exception e){
|
||||
DiscordConfig.deleteAccessToken(state);
|
||||
DiscordConfig.deleteRefreshToken(state);
|
||||
Assert.isTrue(false,e.getMessage());
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
package com.alive.server.api;
|
||||
|
||||
import com.alive.commons.annotation.Login;
|
||||
import com.alive.commons.model.BaseResult;
|
||||
import com.alive.server.api.file.FileModel;
|
||||
import com.alive.server.provider.FileProvider;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import io.swagger.annotations.ApiParam;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.transaction.annotation.Isolation;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.web.bind.annotation.CrossOrigin;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequestMapping("/api/file")
|
||||
@CrossOrigin(origins = "*")
|
||||
@Api(tags = "文件管理")
|
||||
@Transactional(isolation = Isolation.READ_COMMITTED)
|
||||
public class FileController {
|
||||
|
||||
@Autowired
|
||||
private FileProvider fileProvider;
|
||||
|
||||
@Login
|
||||
@PostMapping("uploads")
|
||||
@ApiOperation("多文件上传")
|
||||
public List<FileModel> uploadFiles(@ApiParam("files") @Valid @NotNull(message = "文件不能为空") List<MultipartFile> files) throws IOException {
|
||||
Assert.notNull(files, "多文件上传,参数为files");
|
||||
List<FileModel> respList = new ArrayList<>(files.size());
|
||||
for (MultipartFile file : files) {
|
||||
respList.add(upload(file).getData());
|
||||
}
|
||||
return respList;
|
||||
}
|
||||
|
||||
@Login
|
||||
@PostMapping("upload")
|
||||
@ApiOperation("单上传文件")
|
||||
public BaseResult<FileModel> upload(@ApiParam("file") @Valid @NotNull(message = "文件不能为空") MultipartFile file) throws IOException {
|
||||
return fileProvider.upload(file);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
package com.alive.server.api;
|
||||
|
||||
import com.alive.commons.annotation.Login;
|
||||
import com.alive.db.entity.Vo.InvitationCodeVo;
|
||||
import com.alive.db.entity.Vo.InviteVo;
|
||||
import com.alive.server.service.MemberService;
|
||||
import com.alive.server.service.NodeSettingService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.transaction.annotation.Isolation;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 邀请相关数据
|
||||
*
|
||||
* @author HayDen
|
||||
* @date 2024-01-09
|
||||
*/
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequestMapping("/api/invite")
|
||||
@Api(tags = "邀请数据查询")
|
||||
@Transactional(isolation = Isolation.READ_COMMITTED)
|
||||
public class InviteController
|
||||
{
|
||||
@Autowired
|
||||
private NodeSettingService nodeSettingService;
|
||||
|
||||
@Autowired
|
||||
private MemberService memberService;
|
||||
|
||||
|
||||
/*@Login
|
||||
@GetMapping("getNodeSetting")
|
||||
@ApiOperation("推荐人页面(废弃)")
|
||||
public UserInviteVo findUserInviteVo(){
|
||||
return nodeSettingService.findUserInviteVo();
|
||||
}*/
|
||||
|
||||
@Login
|
||||
@GetMapping("findInviteVoList")
|
||||
@ApiOperation("查询邀请列表")
|
||||
public List<InviteVo> findInviteVoList(){
|
||||
return nodeSettingService.findInviteVoList();
|
||||
}
|
||||
|
||||
@Login
|
||||
@GetMapping("invitationCode")
|
||||
@ApiOperation("查询用户邀请码")
|
||||
public InvitationCodeVo invitationCode(){
|
||||
InvitationCodeVo code = memberService.invitationCode();
|
||||
return code;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,123 @@
|
|||
package com.alive.server.api;
|
||||
|
||||
import com.alive.server.api.account.PayNodeReq;
|
||||
import com.alive.server.api.account.PayNodeSmsReq;
|
||||
import com.alive.commons.annotation.Login;
|
||||
import com.alive.commons.util.DateUtils;
|
||||
import com.alive.commons.util.RedisUtil;
|
||||
import com.alive.db.entity.NodeSetting;
|
||||
import com.alive.db.entity.NodeBuyLog;
|
||||
import com.alive.db.entity.Vo.NoticeOfPaymentVo;
|
||||
import com.alive.db.entity.Vo.WordNodeVo;
|
||||
import com.alive.server.service.NodeBuyLogService;
|
||||
import com.alive.server.service.NodeSettingService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.transaction.annotation.Isolation;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 节点认购记录Controller
|
||||
*
|
||||
* @author HayDen
|
||||
* @date 2024-01-09
|
||||
*/
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequestMapping("/api/node")
|
||||
@Api(tags = "节点购买页面")
|
||||
@Transactional(isolation = Isolation.READ_COMMITTED)
|
||||
public class NodeBuyLogController
|
||||
{
|
||||
@Autowired
|
||||
private NodeSettingService nodeSettingService;
|
||||
|
||||
@Autowired
|
||||
private NodeBuyLogService nodeBuyLogService;
|
||||
|
||||
|
||||
@GetMapping("contractAddress")
|
||||
@ApiOperation("获取合约地址")
|
||||
public Map<String,String> contractAddress(){
|
||||
Map<String,String> map = new HashMap<>();
|
||||
String address = nodeSettingService.contractAddress();
|
||||
map.put("address",address);
|
||||
return map;
|
||||
}
|
||||
|
||||
@GetMapping("getNodeSetting")
|
||||
@ApiOperation("获取节点列表")
|
||||
public List<NodeSetting> getNodeSetting(){
|
||||
List<NodeSetting> nodeSettings = nodeSettingService.selectNodeSettingList(new NodeSetting().setStatus(1));
|
||||
return nodeSettings;
|
||||
}
|
||||
|
||||
@Login
|
||||
@GetMapping("getOrderStateByHash")
|
||||
@ApiOperation("通过hash查询是否购买成功")
|
||||
public Map<String,String> getOrderTypeByHash(String hash){
|
||||
Map<String,String> map = new HashMap<>();
|
||||
map.put("nftIds", RedisUtil.get(hash));
|
||||
return map;
|
||||
}
|
||||
|
||||
@Login
|
||||
@GetMapping("getWOrdNodePro")
|
||||
@ApiOperation("查询我的盒子")
|
||||
public List<WordNodeVo> getWOrdNodePro(){
|
||||
List<WordNodeVo> nodeVoList = nodeSettingService.getWOrdNodePro();
|
||||
for (WordNodeVo vo : nodeVoList){
|
||||
vo.setSpecialAmount("0");
|
||||
Date date = DateUtils.stringByDate("2024-05-07 23:59:59");
|
||||
Date datePas = DateUtils.stringByDate(vo.getCreateTime());
|
||||
if(datePas.getTime() < date.getTime()){
|
||||
vo.setSpecialAmount("38000");
|
||||
}else{
|
||||
vo.setSpecialAmount("10000");
|
||||
}
|
||||
}
|
||||
return nodeVoList;
|
||||
}
|
||||
|
||||
@Login
|
||||
@GetMapping("getWOrdNode")
|
||||
@ApiOperation("查询我的盒子(原接口)")
|
||||
public WordNodeVo getWOrdNode(){
|
||||
return nodeBuyLogService.findWordNodeVo();
|
||||
}
|
||||
|
||||
@Login
|
||||
@PostMapping("pay_node")
|
||||
@ApiOperation("节点下单")
|
||||
public NodeBuyLog payNode(@RequestBody @Validated PayNodeReq req){
|
||||
NodeSetting nodeSetting = nodeSettingService.selectNodeSettingById(req.getNodeId());
|
||||
Assert.isTrue(nodeSetting != null, "Node is null");
|
||||
Assert.isTrue(req.getNumber() <= nodeSetting.getPurchaseLimit(), "Maxi mum pay limit");
|
||||
BigDecimal amount = nodeSetting.getNodePrice().multiply(new BigDecimal(req.getNumber()));
|
||||
Assert.isTrue(amount.compareTo(req.getTatolAmount()) == 0, "Price error");
|
||||
//价格
|
||||
return nodeSettingService.payNode(nodeSetting,req);
|
||||
}
|
||||
|
||||
@Login
|
||||
@GetMapping("pay_node_sms")
|
||||
@ApiOperation("支付通知")
|
||||
public NoticeOfPaymentVo payNodeSms(@Validated PayNodeSmsReq req){
|
||||
log.info("支付成功/失败通知:hash={},orderNumber={},status={}",req.getHash(),req.getOrderNumber(),req.getStatus());
|
||||
NoticeOfPaymentVo vo = new NoticeOfPaymentVo();
|
||||
Boolean result = nodeSettingService.payNodeSms(req);
|
||||
return vo.setType(result ? 1 : 0);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
package com.alive.server.api;
|
||||
|
||||
import com.alive.commons.annotation.Login;
|
||||
import com.alive.commons.model.BasePageReq;
|
||||
import com.alive.db.entity.Vo.MyIntegralVo;
|
||||
import com.alive.db.entity.Vo.NodeTaskVo;
|
||||
import com.alive.db.entity.Vo.TaskVo;
|
||||
import com.alive.server.api.account.TeskReq;
|
||||
import com.alive.server.service.PersonalCenterService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.transaction.annotation.Isolation;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 任务相关
|
||||
*
|
||||
* @author HayDen
|
||||
* @date 2024-01-09
|
||||
*/
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequestMapping("/api/task")
|
||||
@Api(tags = "任务相关")
|
||||
@Transactional(isolation = Isolation.READ_COMMITTED)
|
||||
public class TaskController
|
||||
{
|
||||
@Autowired
|
||||
private PersonalCenterService personalCenterService;
|
||||
|
||||
@Login
|
||||
@GetMapping("myBonusPoints")
|
||||
@ApiOperation("我的积分")
|
||||
public MyIntegralVo myBonusPoints(){
|
||||
MyIntegralVo myIntegralVo = personalCenterService.myBonusPoints();
|
||||
return myIntegralVo;
|
||||
}
|
||||
|
||||
@Login
|
||||
@GetMapping("recommendedCompletionList")
|
||||
@ApiOperation("推荐完成列表(分页)")
|
||||
public List<TaskVo> recommendedCompletionList(BasePageReq basePageReq){
|
||||
return personalCenterService.recommendedCompletionList(basePageReq);
|
||||
}
|
||||
|
||||
@Login
|
||||
@GetMapping("nodeTask")
|
||||
@ApiOperation("奥德赛任务")
|
||||
public List<NodeTaskVo> nodeTask(){
|
||||
return personalCenterService.nodeTask();
|
||||
}
|
||||
|
||||
|
||||
@Login
|
||||
@PostMapping("taskReward")
|
||||
@ApiOperation("领取任务奖励")
|
||||
public Map<String,Boolean> taskReward(@RequestBody @Validated TeskReq req){
|
||||
return personalCenterService.taskReward(req);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,84 @@
|
|||
package com.alive.server.api;
|
||||
|
||||
import com.alive.db.entity.Vo.RecommendVo;
|
||||
import com.alive.server.config.TwitterConfig;
|
||||
import com.alive.server.oss.AliyunOssUtils;
|
||||
import com.alive.server.oss.MultipartFileToFileUtil;
|
||||
import com.alive.server.service.TwitterService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.transaction.annotation.Isolation;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.net.URLEncoder;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Base64;
|
||||
import java.util.Date;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* 个人中心
|
||||
*
|
||||
* @author HayDen
|
||||
* @date 2024-01-09
|
||||
*/
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequestMapping("/api/test")
|
||||
@Api(tags = "测试数据")
|
||||
@Transactional(isolation = Isolation.READ_COMMITTED)
|
||||
public class TestController
|
||||
{
|
||||
@Autowired
|
||||
private TwitterService twitterService;
|
||||
|
||||
|
||||
/**
|
||||
* 上传文件(阿里OSS)
|
||||
*
|
||||
* @param file 文件对象
|
||||
* @return
|
||||
*/
|
||||
@ApiOperation("上传文件")
|
||||
@PostMapping("uploadFile")
|
||||
@ResponseBody
|
||||
public boolean uploadFile() {
|
||||
String saveUrl = "";
|
||||
try {
|
||||
log.info("------文件上传方法执行------");
|
||||
long startTime = System.currentTimeMillis();
|
||||
// 阿里OSS
|
||||
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
|
||||
Date date = new Date();
|
||||
// 阿里云API的文件夹名称(子文件夹)
|
||||
String format = dateFormat.format(date) + "/";
|
||||
// 文件名
|
||||
String formats = String.valueOf(UUID.randomUUID());
|
||||
//File file = new File("");
|
||||
// MultipartFile 转 File
|
||||
//File newFile = MultipartFileToFileUtil.multipartFileToFile(file);
|
||||
File newFile = new File("\"F:\\shenzhencangku_m-wz95qgbprp4ppqnq93io_system.raw\"");
|
||||
// 返回结果 resultArr[0]:唯一MD5数字签名 resultArr[1]:如:"appversion/20200723/a3662009-897c-43ea-a6d8-466ab8310c6b.apk"
|
||||
String[] resultArr = AliyunOssUtils.uploadObject2OSS(newFile);
|
||||
long endTime = System.currentTimeMillis();
|
||||
log.info("------文件上传成功,耗时" + ((endTime - startTime) / 1000) + "s------");
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
log.info("------文件上传失败------");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
package com.alive.server.api;
|
||||
|
||||
import com.alive.commons.config.BaseComponent;
|
||||
import com.alive.commons.util.IntegerUtil;
|
||||
import com.alive.commons.util.RedisUtil;
|
||||
import com.alive.server.config.TwitterConfig;
|
||||
import com.alive.server.dto.TwitterUserDto;
|
||||
import com.alive.server.service.MemberService;
|
||||
import com.alive.server.service.TwitterService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.transaction.annotation.Isolation;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.web.bind.annotation.CrossOrigin;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @anna_gosss
|
||||
* Aabbcc567
|
||||
*/
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequestMapping("/api/twitter")
|
||||
@Api(tags = "推特")
|
||||
@Transactional(isolation = Isolation.READ_COMMITTED)
|
||||
@CrossOrigin(origins = "*")
|
||||
public class TwitterController extends BaseComponent {
|
||||
|
||||
@Autowired
|
||||
private TwitterService twitterService;
|
||||
|
||||
@Autowired
|
||||
private MemberService memberService;
|
||||
|
||||
@GetMapping("callbackUrl")
|
||||
@ApiOperation("授权回调地址")
|
||||
public Map<String,Boolean> callbackUrl(String state, String code) {
|
||||
String key = "CALLBACKURL"+state;
|
||||
Integer value = IntegerUtil.getInteger(RedisUtil.get(key),0);
|
||||
value = value + 1;
|
||||
//防止用户频繁请求授权
|
||||
RedisUtil.setEx(key,value.toString(),60 * 3);
|
||||
|
||||
Map<String,Boolean> map = new HashMap<>();
|
||||
try {
|
||||
state = state.toLowerCase();
|
||||
twitterService.requestBearerToken(state,code);
|
||||
//更新用户推特信息
|
||||
if(memberService.countTwitterUser(state) == 0){
|
||||
//查询用户推特信息
|
||||
TwitterUserDto dto = twitterService.getUserInfoByToken(TwitterConfig.getAccessToken(state));
|
||||
//判断推特是否已绑定
|
||||
twitterService.bindUser(dto.getId());
|
||||
if(dto != null){
|
||||
memberService.renewalUserTwitter(dto,state);
|
||||
}
|
||||
}
|
||||
map.put("result",true);
|
||||
}catch (Exception e){
|
||||
TwitterConfig.deleteAccessToken(state);
|
||||
TwitterConfig.deleteRefreshToken(state);
|
||||
Assert.isTrue(false,e.getMessage());
|
||||
}
|
||||
return map;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
package com.alive.server.api;
|
||||
|
||||
import com.alive.commons.annotation.Login;
|
||||
import com.alive.db.entity.Vo.RecommendVo;
|
||||
import com.alive.db.entity.Vo.TeamRewardVo;
|
||||
import com.alive.server.service.PersonalCenterService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.transaction.annotation.Isolation;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 个人中心
|
||||
*
|
||||
* @author HayDen
|
||||
* @date 2024-01-09
|
||||
*/
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequestMapping("/api/user")
|
||||
@Api(tags = "个人中心")
|
||||
@Transactional(isolation = Isolation.READ_COMMITTED)
|
||||
public class UserController
|
||||
{
|
||||
@Autowired
|
||||
private PersonalCenterService personalCenterService;
|
||||
|
||||
@Login
|
||||
@GetMapping("referralReward")
|
||||
@ApiOperation("推荐奖励")
|
||||
public RecommendVo referralReward(){
|
||||
RecommendVo recommendVo = personalCenterService.referralReward();
|
||||
return recommendVo;
|
||||
}
|
||||
|
||||
@Login
|
||||
@GetMapping("teamList")
|
||||
@ApiOperation("1级团队,2级团队")
|
||||
public List<TeamRewardVo> teamList(Integer grade){
|
||||
Assert.notNull(grade, "Grade is null");
|
||||
return personalCenterService.findTeamRewardVoList(grade);
|
||||
}
|
||||
|
||||
@Login
|
||||
@GetMapping("minerFittings")
|
||||
@ApiOperation("组装矿机需要配件数量")
|
||||
public Map<String,String> minerFittings(){
|
||||
Map<String,String> map = new HashMap<>();
|
||||
map.put("result",personalCenterService.minerFittings());
|
||||
return map;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
package com.alive.server.api.account;
|
||||
|
||||
import com.alive.commons.util.Md5Util;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class AccountCheckCodeReq {
|
||||
|
||||
@ApiModelProperty("1注册,2忘记密码,3转户,4注销账户,5修改密码,6修改支付密码")
|
||||
private int type;
|
||||
|
||||
@ApiModelProperty("账号")
|
||||
private String account;
|
||||
|
||||
private String code;
|
||||
|
||||
@ApiModelProperty("当前时间戳,毫秒")
|
||||
private long timestamp;
|
||||
|
||||
@ApiModelProperty("签名内容,MD5(CHECK{mobile}{timestamp}DAPP)")
|
||||
private String signature;
|
||||
|
||||
public boolean checkSignature() {
|
||||
if (code == null || code.length() != 6) {
|
||||
return false;
|
||||
}
|
||||
if (account == null) {
|
||||
return false;
|
||||
}
|
||||
if (timestamp == 1008610010L && "10000".equals(signature)) {
|
||||
return true;
|
||||
}
|
||||
if (Math.abs(System.currentTimeMillis() - timestamp) > 600_000L) {
|
||||
return false;
|
||||
}
|
||||
return Md5Util.md5(String.format("CHECK%s%dDAPP", account, timestamp)).equalsIgnoreCase(signature);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
package com.alive.server.api.account;
|
||||
|
||||
import com.alive.commons.util.Md5Util;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class AccountGetCodeReq {
|
||||
|
||||
@ApiModelProperty("1注册,2忘记密码,3修改账号,4注销账户,5修改密码,6修改支付密码")
|
||||
private int type;
|
||||
|
||||
@ApiModelProperty("邮箱、账号")
|
||||
private String account;
|
||||
|
||||
@ApiModelProperty("当前时间戳,毫秒")
|
||||
private long timestamp;
|
||||
|
||||
@ApiModelProperty("签名内容,MD5(CODE{mobile}{timestamp}DAPP)")
|
||||
private String signature;
|
||||
|
||||
public boolean checkSignature() {
|
||||
if (account == null) {
|
||||
return false;
|
||||
}
|
||||
if (timestamp == 1008610010L && "10000".equals(signature)) {
|
||||
return true;
|
||||
}
|
||||
if (Math.abs(System.currentTimeMillis() - timestamp) > 600_000L) {
|
||||
return false;
|
||||
}
|
||||
return Md5Util.md5(String.format("CODE%s%dDAPP", account, timestamp)).equalsIgnoreCase(signature);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
package com.alive.server.api.account;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.Max;
|
||||
import javax.validation.constraints.Min;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
@Data
|
||||
public class AccountSignInReq {
|
||||
|
||||
@NotBlank
|
||||
@ApiModelProperty("钱包地址")
|
||||
private String account;
|
||||
|
||||
@NotNull
|
||||
@ApiModelProperty("密码或对MetaBird的签名结果")
|
||||
private String password;
|
||||
|
||||
|
||||
@NotNull
|
||||
@ApiModelProperty("公钥")
|
||||
private String publicKey;
|
||||
|
||||
@NotNull
|
||||
@ApiModelProperty("链类型:1=Bitcoin 2=Ethereum 3=Polygon 4=BNB Chain 5=Arbitrum One")
|
||||
@Min(1)
|
||||
@Max(5)
|
||||
private Integer chainType;
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
package com.alive.server.api.account;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class AccountSignInResp {
|
||||
|
||||
private String token;
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
package com.alive.server.api.account;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.*;
|
||||
|
||||
@Data
|
||||
public class AccountSignUpReq {
|
||||
|
||||
@NotBlank
|
||||
@ApiModelProperty("account")
|
||||
private String account;
|
||||
|
||||
@ApiModelProperty("invitation code")
|
||||
private String shareCode;
|
||||
|
||||
@NotBlank
|
||||
@ApiModelProperty("publicKey")
|
||||
private String publicKey;
|
||||
|
||||
@NotNull
|
||||
@ApiModelProperty("链类型:1=Bitcoin 2=Ethereum 3=Polygon 4=BNB Chain 5=Arbitrum One")
|
||||
@Min(1)
|
||||
@Max(5)
|
||||
private Integer chainType;
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
package com.alive.server.api.account;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class AccountSubResp {
|
||||
|
||||
@ApiModelProperty("当前账号类型,0 普通账号,1主账号,2子账号")
|
||||
private Integer subType;
|
||||
|
||||
@ApiModelProperty("主账号信息,当前是子账号时有值")
|
||||
private String mainAccount;
|
||||
|
||||
@ApiModelProperty("子账号列表,仅在当前是主账号时有值")
|
||||
private List<SubAccountModel> subAccounts;
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
package com.alive.server.api.account;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
import javax.validation.constraints.Size;
|
||||
|
||||
@Data
|
||||
public class AccountUpdatePasswordReq {
|
||||
|
||||
//@NotNull(message = "请输入手机号")
|
||||
@ApiModelProperty("账号")
|
||||
private String account;
|
||||
|
||||
@Size(min = 6, max = 6, message = "please enter the correct verification code")
|
||||
@ApiModelProperty("验证码")
|
||||
private String code;
|
||||
|
||||
////@Size(min = 6, max = 20, message = "请按要求输入密码")
|
||||
@NotNull(message = "Please enter your new password")
|
||||
@ApiModelProperty("新密码")
|
||||
private String password;
|
||||
|
||||
////@Size(min = 6, max = 20, message = "请按要求输入密码")
|
||||
@ApiModelProperty("原密码")
|
||||
private String oldPassword;
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
package com.alive.server.api.account;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class ActivityReq {
|
||||
|
||||
@NotNull(message = "type is null")
|
||||
@ApiModelProperty("1=社交活动 2=测试网络活动")
|
||||
private Integer type;
|
||||
|
||||
@ApiModelProperty("钱包地址")
|
||||
private String address;
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
package com.alive.server.api.account;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class ActivityTaskReq {
|
||||
|
||||
@NotNull(message = "id is null")
|
||||
@ApiModelProperty("活动ID")
|
||||
private Integer id;
|
||||
|
||||
@NotBlank(message = "address is null")
|
||||
@ApiModelProperty("钱包地址")
|
||||
private String address;
|
||||
|
||||
|
||||
@NotNull(message = "type is null")
|
||||
@ApiModelProperty("活动类型 1=推特 2=Discord 3=TG")
|
||||
private String type;
|
||||
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
package com.alive.server.api.account;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.Min;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.math.BigDecimal;
|
||||
|
||||
@Data
|
||||
public class InviteReq {
|
||||
|
||||
@NotBlank(message = "Please enter the invitation code")
|
||||
@ApiModelProperty("invitation code")
|
||||
private String shareCode;
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
package com.alive.server.api.account;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
@Data
|
||||
public class NodeReq {
|
||||
|
||||
@NotNull
|
||||
@ApiModelProperty("节点id")
|
||||
private Integer nodeId;
|
||||
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
package com.alive.server.api.account;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.Max;
|
||||
import javax.validation.constraints.Min;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
@Data
|
||||
public class PayCoinReq {
|
||||
|
||||
@NotNull
|
||||
@ApiModelProperty("币种ID")
|
||||
private Integer coinId;
|
||||
|
||||
@NotBlank
|
||||
@ApiModelProperty("购买数量")
|
||||
private String amount;
|
||||
|
||||
/*@NotBlank
|
||||
@ApiModelProperty("HASH")
|
||||
private String hash;*/
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
package com.alive.server.api.account;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.Min;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.math.BigDecimal;
|
||||
|
||||
@Data
|
||||
public class PayNodeReq {
|
||||
|
||||
@NotNull
|
||||
@ApiModelProperty("节点id")
|
||||
private Integer nodeId;
|
||||
|
||||
@NotNull
|
||||
@ApiModelProperty("购买数量")
|
||||
@Min(value = 1)
|
||||
private Integer number;
|
||||
|
||||
@NotNull
|
||||
@ApiModelProperty("金额")
|
||||
private BigDecimal tatolAmount;
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
package com.alive.server.api.account;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.Min;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
@Data
|
||||
public class PayNodeSmsReq {
|
||||
|
||||
@NotBlank
|
||||
@ApiModelProperty("订单号")
|
||||
private String orderNumber;
|
||||
|
||||
@ApiModelProperty("hash")
|
||||
private String hash;
|
||||
|
||||
@NotNull
|
||||
@ApiModelProperty("1=支付成功 2=取消支付")
|
||||
private Integer status;
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
package com.alive.server.api.account;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class SubAccountModel {
|
||||
|
||||
@ApiModelProperty("手机号")
|
||||
private String mobile;
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
package com.alive.server.api.account;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.Max;
|
||||
import javax.validation.constraints.Min;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
@Data
|
||||
public class TeskReq {
|
||||
|
||||
@NotNull
|
||||
@ApiModelProperty("领取奖励id")
|
||||
private Integer id;
|
||||
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
package com.alive.server.api.account;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class TwitterAuthorizationReq {
|
||||
|
||||
@ApiModelProperty("地址")
|
||||
private String address;
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
package com.alive.server.api.account;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class UserInviteReq {
|
||||
|
||||
@NotBlank(message = "Please enter the invitation address")
|
||||
@ApiModelProperty("地址")
|
||||
private String address;
|
||||
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
package com.alive.server.api.file;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class FileModel {
|
||||
//源文件名
|
||||
private String originFileName;
|
||||
|
||||
//新文件名
|
||||
private String fileName;
|
||||
|
||||
//文件相对路径
|
||||
private String filePath;
|
||||
|
||||
//文件完整url
|
||||
private String fullUrl;
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
package com.alive.server.config;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Data
|
||||
@Configuration
|
||||
@ConfigurationProperties(prefix = "com.alive", ignoreUnknownFields = true)
|
||||
public class DcProperties {
|
||||
|
||||
private Config config = new Config();
|
||||
|
||||
private Upload upload = new Upload();
|
||||
|
||||
@Data
|
||||
public static class Config {
|
||||
|
||||
private String tokenHeader = "Authorization";
|
||||
|
||||
//登录token,redis key格式
|
||||
private String tokenRedisKeyFormat = "jiafu:token:%d:%s";
|
||||
|
||||
//token有效期,1天
|
||||
private long tokenExpireSeconds = 86400;
|
||||
|
||||
//限制只能登录一个
|
||||
private boolean limitLoginOneOnly = false;
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class Upload {
|
||||
|
||||
//文件存储根路径,需要以 / 结尾
|
||||
private String filePath = "/data/upload";
|
||||
|
||||
//默认域名
|
||||
private String defaultUrlPreFix = "http://localhost:8080/file/";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
package com.alive.server.config;
|
||||
|
||||
import com.alive.commons.util.RedisUtil;
|
||||
|
||||
/**
|
||||
* Discord相关配置
|
||||
*/
|
||||
public class DiscordConfig {
|
||||
|
||||
/**
|
||||
* 客户id和客户私钥
|
||||
*/
|
||||
public static final String CLIENT_ID = "1224903279029522605";
|
||||
public static final String CLIENT_SECRET = "6AWmmPdOOJTSx54ObO7s8EdCXQp-Kq4y";
|
||||
public static final String TOKEN_URL = "http://roos.nat300.top";
|
||||
//https://discord.com/channels/981752566729826424/1213733877152219196
|
||||
/**
|
||||
* 用户服务器ID
|
||||
*/
|
||||
public static final String CHANNEL_ID = "981752566729826424";
|
||||
|
||||
/**
|
||||
* 机器人token
|
||||
*/
|
||||
public static final String BOT_TOKEN = "MTIyNDkwMzI3OTAyOTUyMjYwNQ.GjEwjk.tqILxW6gC2E7WIziqtlV_iCe4VEW6M3ILUH1gQ";
|
||||
|
||||
|
||||
private static final String accessTokenCode = "DISCORD_ACCESS_TOKEN";
|
||||
private static final String accessRefreshTokenCode = "DISCORD_ACCESS_REFRESH_TOKEN";
|
||||
|
||||
/**
|
||||
* 保存用户的访问令牌
|
||||
* @return
|
||||
*/
|
||||
public static void addAccessToken(String address,String token,Integer number){
|
||||
RedisUtil.setEx((accessTokenCode+address).toLowerCase(),token,number);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户的访问令牌
|
||||
* @return
|
||||
*/
|
||||
public static String getAccessToken(String address){
|
||||
return RedisUtil.get((accessTokenCode+address).toLowerCase());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 删除访问令牌
|
||||
* @param address
|
||||
*/
|
||||
public static void deleteAccessToken(String address){
|
||||
RedisUtil.del((accessTokenCode+address).toLowerCase());
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存用户的刷新令牌
|
||||
* @return
|
||||
*/
|
||||
public static void addRefreshToken(String address,String token,Integer number){
|
||||
RedisUtil.setEx((accessRefreshTokenCode+address).toLowerCase(),token,number);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户的刷新令牌
|
||||
* @return
|
||||
*/
|
||||
public static String getRefreshToken(String address){
|
||||
return RedisUtil.get((accessRefreshTokenCode+address).toLowerCase());
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除刷新令牌
|
||||
* @param address
|
||||
*/
|
||||
public static void deleteRefreshToken(String address){
|
||||
RedisUtil.del((accessRefreshTokenCode+address).toLowerCase());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
package com.alive.server.config;
|
||||
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Profile;
|
||||
import springfox.documentation.builders.ApiInfoBuilder;
|
||||
import springfox.documentation.builders.ParameterBuilder;
|
||||
import springfox.documentation.builders.PathSelectors;
|
||||
import springfox.documentation.builders.RequestHandlerSelectors;
|
||||
import springfox.documentation.schema.ModelRef;
|
||||
import springfox.documentation.service.Parameter;
|
||||
import springfox.documentation.spi.DocumentationType;
|
||||
import springfox.documentation.spring.web.plugins.Docket;
|
||||
import springfox.documentation.swagger2.annotations.EnableSwagger2;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.sql.Time;
|
||||
import java.sql.Timestamp;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Configuration
|
||||
@EnableSwagger2
|
||||
@Profile({"dev", "test", "uat"})
|
||||
public class SwaggerConfig {
|
||||
|
||||
@Bean
|
||||
public Docket swaggerDocket() {
|
||||
|
||||
List<Parameter> pars = new ArrayList<>();
|
||||
pars.add(buildParameter("Authorization", "全局参数,token", "header", null, false));
|
||||
pars.add(buildParameter("Accept-Language", "全局参数,语言,en,zh-CN", "header", null, false));
|
||||
pars.add(buildParameter("address", "全局参数,地址", "header", null, false));
|
||||
|
||||
return new Docket(DocumentationType.SWAGGER_2)
|
||||
.apiInfo(
|
||||
new ApiInfoBuilder()
|
||||
.title("INODE DOC")
|
||||
.description("I NODE接口文档")
|
||||
.version("1.0")
|
||||
.build()
|
||||
).forCodeGeneration(true)
|
||||
.select()
|
||||
.apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
|
||||
.apis(RequestHandlerSelectors.basePackage("com.alive"))
|
||||
.paths(PathSelectors.any())
|
||||
.build()
|
||||
.directModelSubstitute(Timestamp.class, Long.class)
|
||||
.directModelSubstitute(BigDecimal.class, String.class)
|
||||
.directModelSubstitute(Long.class, String.class)
|
||||
.directModelSubstitute(Time.class, String.class)
|
||||
.globalOperationParameters(pars);
|
||||
}
|
||||
|
||||
private Parameter buildParameter(String name, String description, String type, String defaultValue, boolean required) {
|
||||
return new ParameterBuilder()
|
||||
.name(name)
|
||||
.description(description)
|
||||
.modelRef(new ModelRef("string"))
|
||||
.parameterType(type)
|
||||
.defaultValue(defaultValue)
|
||||
.required(required)
|
||||
.build();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
|
||||
package com.alive.server.config;
|
||||
|
||||
public class TelegramConfig {
|
||||
|
||||
/**
|
||||
* TG 机器人配置
|
||||
*/
|
||||
/*public static final String TG_BOT_TOKEN = "6931894326:AAG7wKXz6KrT7VJEHRpNvRcbS6GAHPXFBfc";
|
||||
public static final String TG_BOT_NAME = "Roos_team_bot";
|
||||
|
||||
*//**
|
||||
* 群聊ID
|
||||
*//*
|
||||
public static final String TG_BOT_TEAM_ID = "-1002057252647";
|
||||
|
||||
*//**
|
||||
* 加入我们的URL
|
||||
*//*
|
||||
public static final String ADD_TG_URL = "https://t.me/roosnetwork";
|
||||
|
||||
|
||||
*//**
|
||||
* 官网链接
|
||||
*//*
|
||||
public static final String APP_TG_URL = "http://roos.nat300.top/";*/
|
||||
|
||||
/**
|
||||
* TG 机器人配置
|
||||
*/
|
||||
public static final String TG_BOT_TOKEN = "6824696533:AAGeZIB4nygsnhbNW8VKgOqNO3zM4eN9BcE";
|
||||
public static final String TG_BOT_NAME = "roos_001_bot";
|
||||
|
||||
/**
|
||||
* 群聊ID
|
||||
*/
|
||||
public static final String TG_BOT_TEAM_ID = "-1002106880389";
|
||||
|
||||
/**
|
||||
* 加入我们的URL
|
||||
*/
|
||||
public static final String ADD_TG_URL = "https://t.me/+DGP8zqISzag0ZmQ1";
|
||||
|
||||
|
||||
/**
|
||||
* 官网链接
|
||||
*/
|
||||
public static final String APP_TG_URL = "http://roos.nat300.top/";
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
package com.alive.server.config;
|
||||
|
||||
/**
|
||||
* 线程池常量.
|
||||
*/
|
||||
public class ThreadPoolConstant {
|
||||
|
||||
/**
|
||||
* 核心线程数量
|
||||
*/
|
||||
public static final int CORE_THREAD_NUM = 30;
|
||||
|
||||
/**
|
||||
* 最大线程数量
|
||||
*/
|
||||
public static final int MAX_THREAD_NUM = 50;
|
||||
|
||||
/**
|
||||
* 非核心线程存活时间
|
||||
*/
|
||||
public static final long KEEP_ALIVE_TIME_SECONDS = 10L;
|
||||
|
||||
/**
|
||||
* 任务队列长度
|
||||
*/
|
||||
public static final int QUEUE_LENGTH = 100;
|
||||
|
||||
/**
|
||||
* 线程超时时间
|
||||
*/
|
||||
public static final long TIME_OUT = 70;
|
||||
|
||||
}
|
|
@ -0,0 +1,96 @@
|
|||
package com.alive.server.config;
|
||||
|
||||
import com.alive.commons.util.RedisUtil;
|
||||
|
||||
/**
|
||||
* 推特相关配置
|
||||
*/
|
||||
public class TwitterConfig {
|
||||
|
||||
/**
|
||||
* 客户id和客户私钥
|
||||
*/
|
||||
public static final String CLIENT_ID = "ZjYyaEJNMHpfbjdEajhWbTE0MlM6MTpjaQ";
|
||||
public static final String CLIENT_SECRET = "n_SJAwD0a7en-JUmsAZrqomSVPZ7if7zCmYNu2OYODNPViCQq4";
|
||||
|
||||
/**
|
||||
* 应用KYE和私钥
|
||||
*/
|
||||
public static final String CONSUMER_KEY = "p095I87anDYwfiSVT8A6Yv6qS";
|
||||
public static final String CONSUMER_SECRET = "h53oVBl0EFoYDpBbiKe57qjVb0cIoTUoavGUYKUfiMCNHvbplw";
|
||||
|
||||
/**
|
||||
* 应用的TOKEN
|
||||
*/
|
||||
public static final String ACCESS_TOKEN = "1744591442130161664-ooAeW9un4WvmzVLV6g6cFau8hAT4fz";
|
||||
public static final String ACCESS_TOKEN_SECRET = "7ysXLOGTUZUPV5ddVc0vDtHqt0y63vQrtL46tZ3XgMQO4";
|
||||
|
||||
/**
|
||||
* 推特开发者账号的访问token
|
||||
*/
|
||||
public static final String AAAA_TOKEN = "AAAAAAAAAAAAAAAAAAAAAH3%2FswEAAAAAZPOg4zlVU6wpdP8vFUrgF8YDT04%3DfzNjjCrU4THOlwHqoR3WNLxFLhlKYayEel5nKXUhm0cwSXfpG1";
|
||||
|
||||
/**
|
||||
* 回调地址
|
||||
*/
|
||||
public static final String CALLBACK_URL="http://roos.nat300.top";
|
||||
|
||||
/**
|
||||
* 开发者推特用户id
|
||||
*/
|
||||
public static final String DEVELOPERS = "1744591442130161664";
|
||||
|
||||
private static final String accessTokenCode = "TWITTER_ACCESS_TOKEN";
|
||||
private static final String accessRefreshTokenCode = "TWITTER_ACCESS_REFRESH_TOKEN";
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 保存用户的访问令牌
|
||||
* @return
|
||||
*/
|
||||
public static void addAccessToken(String address,String token,Integer number){
|
||||
RedisUtil.setEx((accessTokenCode+address).toLowerCase(),token,number);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户的访问令牌
|
||||
* @return
|
||||
*/
|
||||
public static String getAccessToken(String address){
|
||||
return RedisUtil.get((accessTokenCode+address).toLowerCase());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 删除访问令牌
|
||||
* @param address
|
||||
*/
|
||||
public static void deleteAccessToken(String address){
|
||||
RedisUtil.del((accessTokenCode+address).toLowerCase());
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存用户的刷新令牌
|
||||
* @return
|
||||
*/
|
||||
public static void addRefreshToken(String address,String token,Integer number){
|
||||
RedisUtil.setEx((accessRefreshTokenCode+address).toLowerCase(),token,number);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户的刷新令牌
|
||||
* @return
|
||||
*/
|
||||
public static String getRefreshToken(String address){
|
||||
return RedisUtil.get((accessRefreshTokenCode+address).toLowerCase());
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除刷新令牌
|
||||
* @param address
|
||||
*/
|
||||
public static void deleteRefreshToken(String address){
|
||||
RedisUtil.del((accessRefreshTokenCode+address).toLowerCase());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
package com.alive.server.dto;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class AttentionDto {
|
||||
|
||||
/**
|
||||
* true 表示关注成功 false 表示关注失败(目标用户没有公开推文的情况,因为他们必须批准关注者请求)
|
||||
*/
|
||||
private Boolean following;
|
||||
|
||||
/**
|
||||
* 指示目标用户是否需要批准关注请求。请注意,只有当目标用户批准传入的关注者请求时,经过身份验证的用户才会关注目标用户 false就是正常的
|
||||
*/
|
||||
private Boolean pending_follow;
|
||||
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
package com.alive.server.dto;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class DiscordTransshipmentDto{
|
||||
|
||||
private String discordId;
|
||||
|
||||
private String tgId;
|
||||
|
||||
private Integer id;
|
||||
|
||||
private Integer activityConfigId;
|
||||
|
||||
private String address;
|
||||
|
||||
private Integer type;
|
||||
|
||||
private BigDecimal amount;
|
||||
|
||||
private Date createTime;
|
||||
|
||||
private String mark;
|
||||
|
||||
private BigDecimal superiorAmount;
|
||||
|
||||
private Integer configType;
|
||||
|
||||
private String superiorAddress;
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
package com.alive.server.dto;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class DiscordUserDto {
|
||||
|
||||
/**
|
||||
* 服务器ID
|
||||
*/
|
||||
private String guildId;
|
||||
|
||||
/**
|
||||
* 服务器名称
|
||||
*/
|
||||
private String guildName;
|
||||
|
||||
/**
|
||||
* 用户ID
|
||||
*/
|
||||
private String userId;
|
||||
|
||||
/**
|
||||
* 用户名称
|
||||
*/
|
||||
private String userName;
|
||||
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
package com.alive.server.dto;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* 获取工会列表
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class DiscordlaborUnionDto {
|
||||
|
||||
|
||||
/**
|
||||
* 工会ID
|
||||
*/
|
||||
public String id;
|
||||
|
||||
|
||||
/**
|
||||
* 工会名称
|
||||
*/
|
||||
public String name;
|
||||
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
package com.alive.server.dto;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class TransferDto {
|
||||
|
||||
/**
|
||||
* 任务log id
|
||||
*/
|
||||
private Integer id;
|
||||
/**
|
||||
* 用户地址
|
||||
*/
|
||||
private String address;
|
||||
/**
|
||||
* 用户金额
|
||||
*/
|
||||
private BigDecimal amount;
|
||||
|
||||
/**
|
||||
* 上级奖励用户金额
|
||||
*/
|
||||
private BigDecimal superiorAmount;
|
||||
|
||||
/**
|
||||
* 上级地址
|
||||
*/
|
||||
private String superiorAddress;
|
||||
|
||||
/**
|
||||
* 上级用户奖励地址
|
||||
*/
|
||||
private Integer referId;
|
||||
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
package com.alive.server.dto;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class TransshipmentUserDto {
|
||||
|
||||
/**
|
||||
* 用户名
|
||||
*/
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 用户id
|
||||
*/
|
||||
private String id;
|
||||
|
||||
/**
|
||||
* 用户名 @
|
||||
*/
|
||||
private String username;
|
||||
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
package com.alive.server.dto;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class TwitterDto {
|
||||
|
||||
/**
|
||||
* 获取的访问令牌
|
||||
*/
|
||||
private String accessToken;
|
||||
|
||||
/**
|
||||
* 刷新令牌
|
||||
*/
|
||||
private String refreshToken;
|
||||
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
package com.alive.server.dto;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class TwitterThumbsUpDto {
|
||||
|
||||
/**
|
||||
* 喜欢的推文ID
|
||||
*/
|
||||
private String tweetsId;
|
||||
|
||||
/**
|
||||
* 推特ID
|
||||
*/
|
||||
private String teId;
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
package com.alive.server.dto;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class TwitterTransshipmentDto{
|
||||
|
||||
private Integer id;
|
||||
|
||||
|
||||
private Integer activityConfigId;
|
||||
|
||||
private Date createTime;
|
||||
|
||||
private String address;
|
||||
|
||||
private Integer type;
|
||||
|
||||
private BigDecimal amount;
|
||||
|
||||
private BigDecimal superiorAmount;
|
||||
|
||||
private Integer configType;
|
||||
|
||||
private String mark;
|
||||
|
||||
private String twitterId;
|
||||
|
||||
private String superiorAddress;
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
package com.alive.server.dto;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class TwitterUserDto {
|
||||
|
||||
/**
|
||||
* 推特名 @xxxx
|
||||
*/
|
||||
private String username;
|
||||
|
||||
/**
|
||||
* 推特用户名
|
||||
*/
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 推特用户ID
|
||||
*/
|
||||
private String id;
|
||||
|
||||
/**
|
||||
* 推特头像
|
||||
*/
|
||||
private String img;
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
package com.alive.server.dto;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* 用户工会信息
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class UserDto {
|
||||
|
||||
private String id;
|
||||
|
||||
private String username;
|
||||
|
||||
private String locale;
|
||||
|
||||
private String email;
|
||||
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
package com.alive.server.dto;
|
||||
|
||||
import com.alive.commons.enums.WalletLogTypeEnum;
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
@Data
|
||||
public class WalletOperation {
|
||||
|
||||
//类型: 1仅余额,2仅冻结
|
||||
private int type;
|
||||
private int walletId;
|
||||
private WalletLogTypeEnum opType;
|
||||
private BigDecimal opAmount;
|
||||
private String extRemark;
|
||||
|
||||
private WalletOperation() {
|
||||
}
|
||||
|
||||
public static WalletOperation buildParam(int type, int walletId,
|
||||
WalletLogTypeEnum opType,
|
||||
BigDecimal opAmount,
|
||||
String extRemark) {
|
||||
WalletOperation dto = new WalletOperation();
|
||||
dto.type = type;
|
||||
dto.walletId = walletId;
|
||||
dto.opType = opType;
|
||||
dto.opAmount = opAmount;
|
||||
dto.extRemark = extRemark;
|
||||
return dto;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,432 @@
|
|||
package com.alive.server.oss;
|
||||
|
||||
import com.aliyun.oss.ClientBuilderConfiguration;
|
||||
import com.aliyun.oss.OSS;
|
||||
import com.aliyun.oss.OSSClientBuilder;
|
||||
import com.aliyun.oss.OSSException;
|
||||
import com.aliyun.oss.common.auth.CredentialsProvider;
|
||||
import com.aliyun.oss.common.auth.DefaultCredentialProvider;
|
||||
import com.aliyun.oss.model.*;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
public class AliyunOssUtils {
|
||||
|
||||
public static String endpoint = "https://oss-cn-shenzhen.aliyuncs.com";
|
||||
|
||||
//
|
||||
public static String accessKeyId = "LTAI5t9qojLQd7XJ27SLtBvw";
|
||||
public static String accessKeySecret = "RVpT3A9bva47n71E2Pc4k5CI9fprzt";
|
||||
|
||||
// 创建阿里云登录凭证
|
||||
public static CredentialsProvider credentialsProvider = new DefaultCredentialProvider(accessKeyId, accessKeySecret);
|
||||
|
||||
// 创建OSSClient实例。
|
||||
public static OSS ossClient = new OSSClientBuilder().build(endpoint, credentialsProvider);
|
||||
|
||||
/**
|
||||
* 创建bucket
|
||||
*/
|
||||
public static void createBucket(){
|
||||
String bucketName = "java-hello-world";
|
||||
try {
|
||||
// 创建存储空间。
|
||||
ossClient.createBucket(bucketName);
|
||||
} catch (Exception e) {
|
||||
System.out.println("Error Message:" + e.getMessage());
|
||||
} finally {
|
||||
if (ossClient != null) {
|
||||
ossClient.shutdown();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 上传文件
|
||||
*/
|
||||
public static void uploadFile(){
|
||||
// 填写Bucket名称,如果Bucket不存在, 可以先创建一个
|
||||
String bucketName = "java-hello-world";
|
||||
// 填写Object完整路径,需要包含文件名,但不用包含Bucket名称
|
||||
String objectName = "test/test.txt";
|
||||
|
||||
try {
|
||||
String content = "Hello OSS";
|
||||
// 采用字节数组方式上传
|
||||
PutObjectResult putObjectResult = ossClient.putObject(bucketName, objectName, new ByteArrayInputStream(content.getBytes()));
|
||||
System.out.println("putObjectResult = " + putObjectResult.toString());
|
||||
} catch (Exception e) {
|
||||
System.out.println("Error Message:" + e.getMessage());
|
||||
} finally {
|
||||
if (ossClient != null) {
|
||||
ossClient.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载文件
|
||||
*/
|
||||
public static void downloadFile(){
|
||||
// 填写Bucket名称
|
||||
String bucketName = "java-hello-world";
|
||||
// 填写Object完整路径,需要包含文件名,但不用包含Bucket名称
|
||||
String objectName = "test/test.txt";
|
||||
|
||||
try {
|
||||
// 调用ossClient.getObject返回一个OSSObject实例,该实例包含文件内容及文件元信息。
|
||||
OSSObject ossObject = ossClient.getObject(bucketName, objectName);
|
||||
|
||||
// 调用ossObject.getObjectContent获取文件输入流,可读取此输入流获取其内容。
|
||||
InputStream content = ossObject.getObjectContent();
|
||||
|
||||
if (content != null) {
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(content));
|
||||
while (true) {
|
||||
String line = reader.readLine();
|
||||
if (line == null) {
|
||||
break;
|
||||
}
|
||||
System.out.println("\n" + line);
|
||||
}
|
||||
// 数据读取完成后,获取的流必须关闭,否则会造成连接泄漏,导致请求无连接可用,程序无法正常工作。
|
||||
content.close();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
System.out.println("Error Message:" + e.getMessage());
|
||||
} finally {
|
||||
if (ossClient != null) {
|
||||
ossClient.shutdown();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询某个bucket的Object列表
|
||||
*/
|
||||
public static void getObjectList(){
|
||||
// 填写Bucket名称
|
||||
String bucketName = "java-hello-world";
|
||||
|
||||
try {
|
||||
// ossClient.listObjects返回ObjectListing实例,包含此次listObject请求的返回结果。
|
||||
ObjectListing objectListing = ossClient.listObjects(bucketName);
|
||||
|
||||
int size = objectListing.getObjectSummaries().size();
|
||||
System.out.println("=========查询到的对象数量是:"+size);
|
||||
|
||||
// objectListing.getObjectSummaries获取所有文件的描述信息。
|
||||
for (OSSObjectSummary objectSummary : objectListing.getObjectSummaries()) {
|
||||
System.out.println(" ======================== " + objectSummary.getKey() + " " +
|
||||
"(size = " + objectSummary.getSize() + ")");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
System.out.println("Error Message:" + e.getMessage());
|
||||
} finally {
|
||||
if (ossClient != null) {
|
||||
ossClient.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除某个对象
|
||||
*/
|
||||
public static void deleteObject(){
|
||||
// 填写Bucket名称
|
||||
String bucketName = "java-hello-world";
|
||||
// 填写Object完整路径,需要包含文件名,但不用包含Bucket名称
|
||||
String objectName = "test/test.txt";
|
||||
try {
|
||||
// 删除文件
|
||||
ossClient.deleteObject(bucketName, objectName);
|
||||
} catch (OSSException e) {
|
||||
System.out.println("Error Message:" + e.getMessage());
|
||||
} finally {
|
||||
if (ossClient != null) {
|
||||
ossClient.shutdown();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取阿里云OSS客户端对象
|
||||
*
|
||||
* @return ossClient
|
||||
*/
|
||||
public static OSS getOSSClient() {
|
||||
ClientBuilderConfiguration conf = new ClientBuilderConfiguration();
|
||||
// 连接空闲超时时间,超时则关闭
|
||||
conf.setIdleConnectionTime(1000);
|
||||
// 在这里可以做一些配置,比如超时时间、最大连接数之类的
|
||||
return new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret, conf);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建桶
|
||||
*
|
||||
* @param ossClient OSS连接
|
||||
* @param bucketName 桶名称
|
||||
* @return
|
||||
*/
|
||||
public static String createBucketName(OSS ossClient, String bucketName) {
|
||||
if (!ossClient.doesBucketExist(bucketName)) {
|
||||
//创建存储空间
|
||||
Bucket bucket = ossClient.createBucket(bucketName);
|
||||
log.info("创建存储空间成功");
|
||||
return bucket.getName();
|
||||
}
|
||||
return bucketName;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 上传图片至OSS 文件流
|
||||
*
|
||||
* @param ossClient oss连接
|
||||
* @param file 上传文件(文件全路径如:D:\\image\\cake.jpg)
|
||||
* @param bucketName 桶名称
|
||||
* @param folder 阿里云API的文件夹名称(父文件夹)
|
||||
* @param format 阿里云API的文件夹名称(子文件夹)
|
||||
* @param formats 文件名
|
||||
* @return String 返回的唯一MD5数字签名
|
||||
*/
|
||||
public static String[] uploadObject2OSS(File file) {
|
||||
String bucketName= "shenzhencangku";
|
||||
createBucketName(ossClient,bucketName);
|
||||
String folder= "";
|
||||
String format="";
|
||||
String formats="123";
|
||||
// 创建一个可重用固定线程数的线程池
|
||||
ExecutorService executorService = Executors.newFixedThreadPool(5);
|
||||
String[] resultArr = new String[2];
|
||||
try {
|
||||
// 分片上传
|
||||
folder = folder + format;
|
||||
// 文件名
|
||||
String fileName = file.getName();
|
||||
// 文件扩展名
|
||||
String fileExtension = fileName.substring(fileName.lastIndexOf("."));
|
||||
// 最终文件名:UUID + 文件扩展名
|
||||
fileName = formats + fileExtension;
|
||||
fileName = "shenzhencangku_m-wz95qgbprp4ppqnq93io_system.raw";
|
||||
// 上传路径 如:appversion/20200723/a3662009-897c-43ea-a6d8-466ab8310c6b.apk
|
||||
// objectName表示上传文件到OSS时需要指定包含文件后缀在内的完整路径,例如abc/efg/123.jpg
|
||||
String objectName = folder + fileName;
|
||||
log.info("上传到路径:" + objectName);
|
||||
// 文件大小
|
||||
long fileSize = file.length();
|
||||
// 创建上传Object的Metadata
|
||||
ObjectMetadata metadata = new ObjectMetadata();
|
||||
// 指定该Object被下载时的网页的缓存行为
|
||||
metadata.setCacheControl("no-cache");
|
||||
// 指定该Object下设置Header
|
||||
metadata.setHeader("Pragma", "no-cache");
|
||||
// 指定该Object被下载时的内容编码格式
|
||||
metadata.setContentEncoding("utf-8");
|
||||
// 文件的MIME,定义文件的类型及网页编码,决定浏览器将以什么形式、什么编码读取文件。如果用户没有指定则根据Key或文件名的扩展名生成,
|
||||
// 如果没有扩展名则填默认值application/octet-stream
|
||||
metadata.setContentType(getContentType(fileExtension));
|
||||
// 指定该Object被下载时的名称(指示MINME用户代理如何显示附加的文件,打开或下载,及文件名称)
|
||||
metadata.setContentDisposition("filename/filesize=" + fileName + "/" + fileSize + "Byte.");
|
||||
// 创建InitiateMultipartUploadRequest对象
|
||||
InitiateMultipartUploadRequest request = new InitiateMultipartUploadRequest(bucketName, objectName, metadata);
|
||||
// 初始化分片
|
||||
InitiateMultipartUploadResult upresult = ossClient.initiateMultipartUpload(request);
|
||||
// 返回uploadId,它是分片上传事件的唯一标识,您可以根据这个uploadId发起相关的操作,如取消分片上传、查询分片上传等
|
||||
String uploadId = upresult.getUploadId();
|
||||
// partETags是PartETag的集合。PartETag由分片的ETag和分片号组成
|
||||
List<PartETag> partETags = Collections.synchronizedList(new ArrayList<>());
|
||||
// 计算文件有多少个分片
|
||||
final long maxPartCount = 10000;
|
||||
final long fileLength = file.length();
|
||||
long partSize = 1 * 1024 * 1024L; // 初始分片大小为1MB
|
||||
|
||||
// 计算分片数量,如果分片数量超过10000,则增大分片大小
|
||||
long partCount = (fileLength / partSize);
|
||||
if (fileLength % partSize != 0) {
|
||||
partCount++;
|
||||
}
|
||||
while (partCount > maxPartCount) {
|
||||
partSize *= 2; // 将分片大小增加一倍
|
||||
partCount = (fileLength / partSize);
|
||||
if (fileLength % partSize != 0) {
|
||||
partCount++;
|
||||
}
|
||||
}
|
||||
|
||||
if (partCount > 10000) {
|
||||
throw new RuntimeException("分片总块数不能超过10000");
|
||||
} else {
|
||||
log.info("分片总块数:" + partCount);
|
||||
}
|
||||
|
||||
// 遍历分片上传
|
||||
for (int i = 0; i < partCount; i++) {
|
||||
long startPos = i * partSize;
|
||||
long curPartSize = (i + 1 == partCount) ? (fileLength - startPos) : partSize;
|
||||
int partNumber = i + 1;
|
||||
|
||||
// 实现并启动线程
|
||||
executorService.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
InputStream inputStream = null;
|
||||
try {
|
||||
inputStream = new FileInputStream(file);
|
||||
// 跳过已经上传的分片
|
||||
inputStream.skip(startPos);
|
||||
UploadPartRequest uploadPartRequest = new UploadPartRequest();
|
||||
uploadPartRequest.setBucketName(bucketName);
|
||||
uploadPartRequest.setKey(objectName);
|
||||
uploadPartRequest.setUploadId(uploadId);
|
||||
uploadPartRequest.setInputStream(inputStream);
|
||||
// 设置分片大小。除了最后一个分片没有大小限制,其他的分片最小为100 KB。
|
||||
uploadPartRequest.setPartSize(curPartSize);
|
||||
// 设置分片号。每一个上传的分片都有一个分片号,取值范围是1~10000,如果超出这个范围,OSS将返回InvalidArgument的错误码。
|
||||
uploadPartRequest.setPartNumber(partNumber);
|
||||
// 每个分片不需要按顺序上传,甚至可以在不同客户端上传,OSS会按照分片号排序组成完整的文件。
|
||||
UploadPartResult uploadPartResult = ossClient.uploadPart(uploadPartRequest);
|
||||
// 每次上传分片之后,OSS的返回结果会包含一个PartETag。PartETag将被保存到PartETags中。
|
||||
synchronized (partETags) {
|
||||
partETags.add(uploadPartResult.getPartETag());
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
if (inputStream != null) {
|
||||
try {
|
||||
inputStream.close();
|
||||
} catch (IOException e) {
|
||||
log.error(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 等待所有的分片完成
|
||||
// shutdown方法:通知各个任务(Runnable)的运行结束
|
||||
executorService.shutdown();
|
||||
while (!executorService.isTerminated()) {
|
||||
try {
|
||||
// 指定的时间内所有的任务都结束的时候,返回true,反之返回false,返回false还有执行完的任务
|
||||
executorService.awaitTermination(5, TimeUnit.SECONDS);
|
||||
} catch (InterruptedException e) {
|
||||
log.error(e.getMessage());
|
||||
}
|
||||
}
|
||||
// 立即关闭所有执行中的线程
|
||||
// executorService.shutdownNow();
|
||||
|
||||
// 验证是否所有的分片都完成
|
||||
if (partETags.size() != partCount) {
|
||||
throw new IllegalStateException("文件的某些部分上传失败!");
|
||||
} else {
|
||||
log.info("文件上传成功:" + file.getName());
|
||||
}
|
||||
// 完成分片上传 进行排序。partETags必须按分片号升序排列
|
||||
Collections.sort(partETags, new Comparator<PartETag>() {
|
||||
@Override
|
||||
public int compare(PartETag o1, PartETag o2) {
|
||||
return o1.getPartNumber() - o2.getPartNumber();
|
||||
}
|
||||
});
|
||||
// 创建CompleteMultipartUploadRequest对象
|
||||
// 在执行完成分片上传操作时,需要提供所有有效的partETags。OSS收到提交的partETags后,会逐一验证每个分片的有效性。当所有的数据分片验证通过后,OSS将把这些分片组合成一个完整的文件
|
||||
CompleteMultipartUploadRequest completeMultipartUploadRequest = new CompleteMultipartUploadRequest(bucketName, objectName, uploadId, partETags);
|
||||
// 设置文件访问权限
|
||||
// completeMultipartUploadRequest.setObjectACL(CannedAccessControlList.PublicRead);
|
||||
// 完成上传
|
||||
CompleteMultipartUploadResult completeMultipartUploadResult = ossClient.completeMultipartUpload(completeMultipartUploadRequest);
|
||||
if (completeMultipartUploadResult != null) {
|
||||
// 解析结果
|
||||
resultArr[0] = completeMultipartUploadResult.getETag();
|
||||
resultArr[1] = objectName;
|
||||
return resultArr;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
log.error("上传阿里云OSS服务器异常." + e.getMessage(), e);
|
||||
} finally {
|
||||
// 关闭OSSClient
|
||||
ossClient.shutdown();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过文件名判断并获取OSS服务文件上传时文件的contentType
|
||||
*
|
||||
* @param fileExtension 文件名扩展名
|
||||
* @return 文件的contentType
|
||||
*/
|
||||
public static String getContentType(String fileExtension) {
|
||||
// 文件的后缀名
|
||||
if (".bmp".equalsIgnoreCase(fileExtension)) {
|
||||
return "image/bmp";
|
||||
}
|
||||
if (".gif".equalsIgnoreCase(fileExtension)) {
|
||||
return "image/gif";
|
||||
}
|
||||
if (".jpeg".equalsIgnoreCase(fileExtension) || ".jpg".equalsIgnoreCase(fileExtension)
|
||||
|| ".png".equalsIgnoreCase(fileExtension)) {
|
||||
return "image/jpeg";
|
||||
}
|
||||
if (".html".equalsIgnoreCase(fileExtension)) {
|
||||
return "text/html";
|
||||
}
|
||||
if (".txt".equalsIgnoreCase(fileExtension)) {
|
||||
return "text/plain";
|
||||
}
|
||||
if (".vsd".equalsIgnoreCase(fileExtension)) {
|
||||
return "application/vnd.visio";
|
||||
}
|
||||
if (".ppt".equalsIgnoreCase(fileExtension) || "pptx".equalsIgnoreCase(fileExtension)) {
|
||||
return "application/vnd.ms-powerpoint";
|
||||
}
|
||||
if (".doc".equalsIgnoreCase(fileExtension) || "docx".equalsIgnoreCase(fileExtension)) {
|
||||
return "application/msword";
|
||||
}
|
||||
if (".xml".equalsIgnoreCase(fileExtension)) {
|
||||
return "text/xml";
|
||||
}
|
||||
if (".mp4".equalsIgnoreCase(fileExtension)) {
|
||||
return "video/mp4";
|
||||
}
|
||||
// android
|
||||
if (".apk".equalsIgnoreCase(fileExtension)) {
|
||||
return "application/vnd.android.package-archive";
|
||||
}
|
||||
// ios
|
||||
if (".ipa".equals(fileExtension)) {
|
||||
return "application/vnd.iphone";
|
||||
}
|
||||
// 默认返回类型
|
||||
return "application/octet-stream";
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
uploadFile();
|
||||
// downloadFile();
|
||||
// getObjectList();
|
||||
// deleteObject();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
package com.alive.server.oss;
|
||||
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
/**
|
||||
* 文件转换工具类
|
||||
*
|
||||
* @author xiegege
|
||||
* @date 2020-07-23
|
||||
*/
|
||||
public class MultipartFileToFileUtil {
|
||||
|
||||
/**
|
||||
* MultipartFile 转 File
|
||||
*
|
||||
* @param file
|
||||
* @throws Exception
|
||||
*/
|
||||
public static File multipartFileToFile(MultipartFile file) {
|
||||
try {
|
||||
File toFile;
|
||||
if (file != null && file.getSize() > 0) {
|
||||
InputStream ins = null;
|
||||
ins = file.getInputStream();
|
||||
toFile = new File(file.getOriginalFilename());
|
||||
inputStreamToFile(ins, toFile);
|
||||
ins.close();
|
||||
return toFile;
|
||||
}
|
||||
return null;
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取流文件
|
||||
*
|
||||
* @param ins
|
||||
* @param file
|
||||
*/
|
||||
public static void inputStreamToFile(InputStream ins, File file) {
|
||||
try {
|
||||
OutputStream os = new FileOutputStream(file);
|
||||
int bytesRead;
|
||||
byte[] buffer = new byte[8192];
|
||||
while ((bytesRead = ins.read(buffer, 0, 8192)) != -1) {
|
||||
os.write(buffer, 0, bytesRead);
|
||||
}
|
||||
os.close();
|
||||
ins.close();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除本地临时文件
|
||||
*
|
||||
* @param file
|
||||
*/
|
||||
public static void deleteTempFile(File file) {
|
||||
if (file != null) {
|
||||
File del = new File(file.toURI());
|
||||
del.delete();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
package com.alive.server.provider;
|
||||
|
||||
import com.alive.server.api.file.FileModel;
|
||||
import com.alive.commons.model.BaseResult;
|
||||
import org.springframework.cloud.openfeign.FeignClient;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.bind.annotation.RequestPart;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
@FeignClient(name = "file-provider")
|
||||
public interface FileProvider {
|
||||
|
||||
@RequestMapping(value = "/api/file/upload", method = RequestMethod.POST,
|
||||
consumes = MediaType.MULTIPART_FORM_DATA_VALUE,
|
||||
produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
BaseResult<FileModel> upload(@RequestPart("file") MultipartFile file);
|
||||
}
|
|
@ -0,0 +1,381 @@
|
|||
package com.alive.server.service;
|
||||
|
||||
|
||||
import com.alive.db.entity.Vo.*;
|
||||
import com.alive.server.api.account.ActivityReq;
|
||||
import com.alive.server.api.account.ActivityTaskReq;
|
||||
import com.alive.server.api.account.UserInviteReq;
|
||||
import com.alive.commons.model.BasePageReq;
|
||||
import com.alive.commons.util.DateUtils;
|
||||
import com.alive.commons.util.IntegerUtil;
|
||||
import com.alive.commons.util.RedisUtil;
|
||||
import com.alive.db.jooq.tables.records.ActivityConfigRecord;
|
||||
import com.alive.db.jooq.tables.records.ActivityLogRecord;
|
||||
import com.alive.db.jooq.tables.records.ActivityStatisticsRecord;
|
||||
import com.alive.db.jooq.tables.records.TMemberRecord;
|
||||
import com.alive.db.mapper.ActivityMapper;
|
||||
import com.alive.server.config.DiscordConfig;
|
||||
import com.alive.server.config.TelegramConfig;
|
||||
import com.alive.server.config.TwitterConfig;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.jooq.DSLContext;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Isolation;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.sql.Timestamp;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalTime;
|
||||
import java.util.*;
|
||||
|
||||
import static com.alive.db.jooq.Tables.*;
|
||||
import static com.sun.org.apache.xalan.internal.xsltc.compiler.Constants.CHARACTERS;
|
||||
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
public class ActivityService {
|
||||
|
||||
@Autowired
|
||||
private DSLContext dslContext;
|
||||
|
||||
@Autowired
|
||||
private TwitterService twitterService;
|
||||
|
||||
@Autowired
|
||||
private DiscordService discordService;
|
||||
|
||||
@Autowired
|
||||
private ActivityMapper activityMapper;
|
||||
|
||||
/**
|
||||
* 查询活动列表
|
||||
* @param activityReq
|
||||
* @return
|
||||
*/
|
||||
public List<ActivityConfigVo> findActivityList(ActivityReq activityReq) {
|
||||
List<ActivityConfigVo> activityConfigVos = dslContext.select(ACTIVITY_CONFIG.ID.as("id"),ACTIVITY_CONFIG.TITLE.as("title"),ACTIVITY_CONFIG.TITLE_CONTENT.as("titleContent"),ACTIVITY_CONFIG.ACTIVITY_IMG.as("activityImg")
|
||||
,ACTIVITY_CONFIG.ACTIVITY_URL.as("activityUrl"),ACTIVITY_CONFIG.AMOUNT.as("amount"),ACTIVITY_CONFIG.TYPE.as("type"),ACTIVITY_CONFIG.STATE.as("state")
|
||||
,ACTIVITY_CONFIG.ACTIVITY_NUMBER.as("activityNumber"))
|
||||
.from(ACTIVITY_CONFIG).where(ACTIVITY_CONFIG.STATE.in(1,2)
|
||||
.and(ACTIVITY_CONFIG.CATEGORY.eq(activityReq.getType()))).orderBy(ACTIVITY_CONFIG.ID.desc()).fetchInto(ActivityConfigVo.class);
|
||||
if(StringUtils.isBlank(activityReq.getAddress())){
|
||||
activityConfigVos.forEach(config -> {
|
||||
config.setActualAmount("0");
|
||||
config.setAmount(new BigDecimal(config.getAmount()).stripTrailingZeros().toPlainString());
|
||||
config.setState(4);
|
||||
});
|
||||
}else{
|
||||
TMemberRecord tMemberRecord = dslContext.fetchOne(T_MEMBER, T_MEMBER.ACCOUNT.eq(activityReq.getAddress()));
|
||||
Boolean invite = true;
|
||||
if(tMemberRecord.getReferId() != null && tMemberRecord.getReferId() != 0){
|
||||
//已经绑定上级了,判断任务里面是否有绑定任务的数据
|
||||
Date date = DateUtils.stringByDate("2024-05-15 23:59:59");
|
||||
//以前绑定过上级的用户现在不在查询绑定邀请码这条任务数据了
|
||||
if(date.getTime() < System.currentTimeMillis()){
|
||||
invite = false;
|
||||
}
|
||||
}
|
||||
if(!invite){
|
||||
activityConfigVos = dslContext.select(ACTIVITY_CONFIG.ID.as("id"),ACTIVITY_CONFIG.TITLE.as("title"),ACTIVITY_CONFIG.TITLE_CONTENT.as("titleContent"),ACTIVITY_CONFIG.ACTIVITY_IMG.as("activityImg")
|
||||
,ACTIVITY_CONFIG.ACTIVITY_URL.as("activityUrl"),ACTIVITY_CONFIG.AMOUNT.as("amount"),ACTIVITY_CONFIG.TYPE.as("type"),ACTIVITY_CONFIG.STATE.as("state")
|
||||
,ACTIVITY_CONFIG.ACTIVITY_NUMBER.as("activityNumber"))
|
||||
.from(ACTIVITY_CONFIG).where(ACTIVITY_CONFIG.STATE.in(1,2).andNot(ACTIVITY_CONFIG.TYPE.eq(9))
|
||||
.and(ACTIVITY_CONFIG.CATEGORY.eq(activityReq.getType()))).orderBy(ACTIVITY_CONFIG.ID.desc()).fetchInto(ActivityConfigVo.class);
|
||||
}
|
||||
//一次性任务
|
||||
List<Integer> configIds = new ArrayList<>();
|
||||
//每天可以做一次任务
|
||||
List<Integer> configIds1 = new ArrayList<>();
|
||||
activityConfigVos.forEach(l -> {
|
||||
l.setAmount(new BigDecimal(l.getAmount()).stripTrailingZeros().toPlainString());
|
||||
if(l.getActivityNumber().equals(-1)){
|
||||
configIds.add(l.getId());
|
||||
}else{
|
||||
configIds1.add(l.getId());
|
||||
}
|
||||
});
|
||||
//查询一次性任务完成情况
|
||||
List<ActivityLogRecord> logRecords = dslContext.select(ACTIVITY_LOG.ACTIVITY_CONFIG_ID,ACTIVITY_LOG.AMOUNT,ACTIVITY_LOG.TYPE,ACTIVITY_LOG.ID).from(ACTIVITY_LOG)
|
||||
.where(ACTIVITY_LOG.ADDRESS.eq(activityReq.getAddress()).and(ACTIVITY_LOG.ACTIVITY_CONFIG_ID.in(configIds))
|
||||
.and(ACTIVITY_LOG.TYPE.in(1,2))).fetchInto(ActivityLogRecord.class);
|
||||
Map<Integer,ActivityLogRecord> configs = new HashMap<>();
|
||||
logRecords.forEach(l -> {
|
||||
configs.put(l.getActivityConfigId(),l);
|
||||
});
|
||||
|
||||
//获取当日的开始和结束时间 每天可以完成一次的任务
|
||||
LocalDateTime startOfDay = LocalDate.now().atStartOfDay();
|
||||
LocalDateTime endOfDay = LocalDate.now().atTime(LocalTime.MAX);
|
||||
logRecords = dslContext.select(ACTIVITY_LOG.ACTIVITY_CONFIG_ID,ACTIVITY_LOG.AMOUNT,ACTIVITY_LOG.TYPE).from(ACTIVITY_LOG)
|
||||
.where(ACTIVITY_LOG.ADDRESS.eq(activityReq.getAddress()).and(ACTIVITY_LOG.ACTIVITY_CONFIG_ID.in(configIds1)).and(ACTIVITY_LOG.TYPE.in(1,2))
|
||||
.and(ACTIVITY_LOG.END_TIME.between(Timestamp.valueOf(startOfDay),Timestamp.valueOf(endOfDay)))).fetchInto(ActivityLogRecord.class);
|
||||
Map<Integer,ActivityLogRecord> dayConfigs = new HashMap<>();
|
||||
logRecords.forEach(l -> {
|
||||
dayConfigs.put(l.getActivityConfigId(),l);
|
||||
});
|
||||
for (ActivityConfigVo con : activityConfigVos){
|
||||
if(con.getActivityNumber().equals(-1)){
|
||||
ActivityLogRecord log = configs.get(con.getId());
|
||||
if(log != null){
|
||||
con.setActualAmount(log.getAmount().stripTrailingZeros().toPlainString());
|
||||
con.setState(log.getType() == 1 ? 6 : 5);
|
||||
}
|
||||
}else{
|
||||
ActivityLogRecord log = dayConfigs.get(con.getId());
|
||||
if(log != null){
|
||||
con.setActualAmount(log.getAmount().stripTrailingZeros().toPlainString());
|
||||
con.setState(log.getType() == 1 ? 6 : 5);
|
||||
}
|
||||
}
|
||||
if(con.getType().equals(9) && tMemberRecord.getReferId() != null && tMemberRecord.getReferId() != 0){
|
||||
con.setState(5);
|
||||
}
|
||||
}
|
||||
}
|
||||
return activityConfigVos;
|
||||
}
|
||||
|
||||
/**
|
||||
* 统计活动参数数量
|
||||
* @param activityOutcomeVo
|
||||
* @param activityReq
|
||||
*/
|
||||
public void countActivity(ActivityOutcomeVo activityOutcomeVo, ActivityReq activityReq) {
|
||||
if(StringUtils.isBlank(activityReq.getAddress())){
|
||||
activityOutcomeVo.setAmount("0");
|
||||
}else{
|
||||
BigDecimal amount = dslContext.select(ACTIVITY_STATISTICS.AMOUNT.sum()).from(ACTIVITY_STATISTICS).where(ACTIVITY_STATISTICS.ADDRESS.eq(activityReq.getAddress())).fetchAnyInto(BigDecimal.class);
|
||||
activityOutcomeVo.setAmount(amount == null ? "0" : amount.stripTrailingZeros().toPlainString());
|
||||
TMemberRecord user = dslContext.selectFrom(T_MEMBER).where(T_MEMBER.ACCOUNT.eq(activityReq.getAddress())).fetchAny();
|
||||
Assert.notNull(user, "user is null");
|
||||
activityOutcomeVo.setCodePrompt(user.getCodePrompt());
|
||||
}
|
||||
activityOutcomeVo.setUsesNumber(dslContext.selectCount().from("(SELECT COUNT(0) FROM activity_log WHERE type=3 GROUP BY address) as t").fetchAnyInto(Integer.class));
|
||||
}
|
||||
|
||||
/**
|
||||
* 开始活动任务
|
||||
* @param activityTaskReq
|
||||
*/
|
||||
@Transactional(isolation = Isolation.READ_COMMITTED,readOnly = false)
|
||||
public void startTheTask(ActivityTaskVo activityOutcomeVo, ActivityTaskReq activityTaskReq) {
|
||||
TMemberRecord user = dslContext.selectFrom(T_MEMBER).where(T_MEMBER.ACCOUNT.eq(activityTaskReq.getAddress())).fetchAny();
|
||||
Assert.notNull(user, "please link your wallet first");
|
||||
if(user.getCodePrompt().equals(0)){
|
||||
dslContext.update(T_MEMBER).set(T_MEMBER.CODE_PROMPT,1).where(T_MEMBER.ACCOUNT.eq(activityTaskReq.getAddress())).execute();
|
||||
}
|
||||
activityOutcomeVo.setType(1);
|
||||
ActivityConfigRecord configRecord = dslContext.selectFrom(ACTIVITY_CONFIG).where(ACTIVITY_CONFIG.ID.eq(activityTaskReq.getId())).fetchAny();
|
||||
Assert.notNull(configRecord, "the active configuration does not exist");
|
||||
Assert.isTrue(configRecord.getState().equals(1),"the event does not exist or has been deactivated");
|
||||
if(configRecord.getActivityNumber().equals(-1)){
|
||||
Assert.isTrue(dslContext.selectCount().from(ACTIVITY_LOG).where(ACTIVITY_LOG.ADDRESS.eq(activityTaskReq.getAddress())
|
||||
.and(ACTIVITY_LOG.TYPE.eq(2)).and(ACTIVITY_LOG.ACTIVITY_CONFIG_ID.eq(configRecord.getId()))).fetchAnyInto(Integer.class) == 0,
|
||||
"you have completed the task");
|
||||
}else{
|
||||
//获取当日的开始和结束时间 每天可以完成一次的任务
|
||||
LocalDateTime startOfDay = LocalDate.now().atStartOfDay();
|
||||
LocalDateTime endOfDay = LocalDate.now().atTime(LocalTime.MAX);
|
||||
Assert.isTrue(dslContext.selectCount().from(ACTIVITY_LOG).where(ACTIVITY_LOG.ADDRESS.eq(activityTaskReq.getAddress())
|
||||
.and(ACTIVITY_LOG.TYPE.eq(2)).and(ACTIVITY_LOG.ACTIVITY_CONFIG_ID.eq(configRecord.getId()))
|
||||
.and(ACTIVITY_LOG.END_TIME.between(Timestamp.valueOf(startOfDay),Timestamp.valueOf(endOfDay)))).fetchAnyInto(Integer.class) == 0,
|
||||
"you have completed the task");
|
||||
}
|
||||
activityOutcomeVo.setActivityUrl(configRecord.getActivityUrl());
|
||||
if(configRecord.getType().equals(9) && user.getReferId() != null && user.getReferId() != 0){
|
||||
Assert.isTrue(false,"you have bound a superior inviter");
|
||||
}
|
||||
|
||||
//如果原来有未完成的直接失败处理
|
||||
dslContext.update(ACTIVITY_LOG).set(ACTIVITY_LOG.TYPE,3).where(ACTIVITY_LOG.ADDRESS.eq(activityTaskReq.getAddress())
|
||||
.and(ACTIVITY_LOG.TYPE.eq(1)).and(ACTIVITY_LOG.ACTIVITY_CONFIG_ID.eq(configRecord.getId()))).execute();
|
||||
|
||||
if(configRecord.getType() >= 1 && configRecord.getType() <= 5){
|
||||
//推特授权链接
|
||||
String accessToken = TwitterConfig.getAccessToken(activityTaskReq.getAddress());
|
||||
String refreshToken = TwitterConfig.getRefreshToken(activityTaskReq.getAddress());
|
||||
if(accessToken == null && refreshToken != null){
|
||||
//刷新令牌存在,直接使用刷新令牌刷新
|
||||
twitterService.requestBearerToken(activityTaskReq.getAddress(),null);
|
||||
accessToken = TwitterConfig.getAccessToken(activityTaskReq.getAddress());
|
||||
refreshToken = TwitterConfig.getRefreshToken(activityTaskReq.getAddress());
|
||||
}
|
||||
if(accessToken == null || refreshToken == null){
|
||||
//返回授权链接
|
||||
Assert.isTrue(IntegerUtil.getInteger(RedisUtil.get("CALLBACKURL"+activityTaskReq.getAddress()),0) < 3,
|
||||
"frequent authorizations please try again later");
|
||||
String url = twitterService.getAuthorizationUrl(activityTaskReq.getAddress()+"+"+activityTaskReq.getType());
|
||||
activityOutcomeVo.setAuthorizationLinks(url);
|
||||
}
|
||||
}
|
||||
//Discord 授权
|
||||
if(configRecord.getType().equals(6)){
|
||||
String accessToken = DiscordConfig.getAccessToken(activityTaskReq.getAddress());
|
||||
String refreshToken = DiscordConfig.getRefreshToken(activityTaskReq.getAddress());
|
||||
if(accessToken == null && refreshToken != null){
|
||||
//刷新令牌存在,直接使用刷新令牌刷新
|
||||
discordService.getTokenByCode(null,activityTaskReq.getAddress());
|
||||
accessToken = DiscordConfig.getAccessToken(activityTaskReq.getAddress());
|
||||
refreshToken = DiscordConfig.getRefreshToken(activityTaskReq.getAddress());
|
||||
}
|
||||
if(accessToken == null || refreshToken == null){
|
||||
//返回授权链接
|
||||
Assert.isTrue(IntegerUtil.getInteger(RedisUtil.get("AUTHORIZATIONCALLBACKSTOKEN"+activityTaskReq.getAddress()),0) < 3,
|
||||
"frequent authorizations please try again later");
|
||||
String url = discordService.getAuthorizationUrl(activityTaskReq.getAddress()+"+"+activityTaskReq.getType());
|
||||
activityOutcomeVo.setAuthorizationLinks(url);
|
||||
}
|
||||
}
|
||||
//TG 链接
|
||||
if(configRecord.getType().equals(10)){
|
||||
String tgUrl = "https://t.me/"+ TelegramConfig.TG_BOT_NAME+"?start="+user.getAccount();
|
||||
activityOutcomeVo.setActivityUrl(tgUrl);
|
||||
}
|
||||
|
||||
//创建任务
|
||||
ActivityLogRecord log = dslContext.newRecord(ACTIVITY_LOG);
|
||||
log.setActivityConfigId(configRecord.getId());
|
||||
log.setAddress(activityTaskReq.getAddress());
|
||||
log.setTitle(configRecord.getTitle());
|
||||
log.setType(1);
|
||||
log.setMark(configRecord.getMark());
|
||||
log.setAmount(configRecord.getAmount());
|
||||
log.setSuperiorAmount(configRecord.getSuperiorAmount());
|
||||
if(user.getReferId() != null && user.getReferId() != 0){
|
||||
user = dslContext.selectFrom(T_MEMBER).where(T_MEMBER.ID.eq(user.getReferId())).fetchAny();
|
||||
log.setSuperiorAddress(user != null ? user.getAccount() : null);
|
||||
}else{
|
||||
log.setSuperiorAmount(BigDecimal.ZERO);
|
||||
}
|
||||
log.setConfigType(configRecord.getType());
|
||||
log.store();
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询邀请页面数据
|
||||
* @param activityOutcomeVo
|
||||
* @param address
|
||||
*/
|
||||
public void invitation(InviteCountVo activityOutcomeVo, String address) {
|
||||
TMemberRecord tMemberRecord = dslContext.selectFrom(T_MEMBER).where(T_MEMBER.ACCOUNT.eq(address)).fetchAny();
|
||||
List<TMemberRecord> users = dslContext.select().from(T_MEMBER).where(T_MEMBER.REFER_ID.eq(tMemberRecord.getId())).fetchInto(TMemberRecord.class);
|
||||
activityOutcomeVo.setInvitationCode(tMemberRecord.getShareCode());
|
||||
activityOutcomeVo.setInvitationRewards(BigDecimal.ZERO);
|
||||
activityOutcomeVo.setUserNumber(0);
|
||||
if(users != null && users.size() > 0){
|
||||
Map<String,TMemberRecord> map = new HashMap<>();
|
||||
users.forEach(u -> map.put(u.getAccount(),u));
|
||||
activityOutcomeVo.setUserNumber(users.size());
|
||||
BigDecimal amount = BigDecimal.ZERO;
|
||||
List<InviteContributeVo> list = activityMapper.findInviteContributeVoList(map.keySet());
|
||||
Map<String,InviteContributeVo> mapInvite = new HashMap<>();
|
||||
list.forEach(m -> mapInvite.put(m.getAddress(),m));
|
||||
|
||||
List<InviteContributeVo> voList = new ArrayList<>();
|
||||
for (String key : map.keySet()){
|
||||
InviteContributeVo vo = mapInvite.get(key);
|
||||
if(vo == null){
|
||||
vo = new InviteContributeVo();
|
||||
Integer lent = key.length();
|
||||
vo.setUserName(key.substring(0,5)+"...."+key.substring(lent-5,lent));
|
||||
voList.add(vo);
|
||||
continue;
|
||||
}
|
||||
if(vo.getUserName().length() >= 20){
|
||||
Integer lent = vo.getUserName().length();
|
||||
vo.setUserName(vo.getUserName().substring(0,5)+"...."+vo.getUserName().substring(lent-5,lent));
|
||||
}
|
||||
amount = amount.add(vo.getInvitationRewards());
|
||||
activityOutcomeVo.setInvitationRewards(amount);
|
||||
voList.add(vo);
|
||||
}
|
||||
activityOutcomeVo.setInviteContributeVoList(voList);
|
||||
}
|
||||
}
|
||||
|
||||
//查询排行榜
|
||||
public RankingSummaryVo ranking(BasePageReq req, UserInviteReq userInviteReq) {
|
||||
RankingSummaryVo wordRanking = activityMapper.findRankingSummaryVo(userInviteReq.getAddress());
|
||||
if(wordRanking == null){
|
||||
wordRanking = new RankingSummaryVo();
|
||||
wordRanking.setAmount("0");
|
||||
}else{
|
||||
TMemberRecord tMemberRecord = dslContext.select().from(T_MEMBER).where(T_MEMBER.ACCOUNT.eq(userInviteReq.getAddress())).fetchAnyInto(TMemberRecord.class);
|
||||
wordRanking.setUserImg(tMemberRecord.getTwitterImg());
|
||||
wordRanking.setUserName(tMemberRecord.getTwitterUserName() == null ? tMemberRecord.getAccount() : tMemberRecord.getTwitterName());
|
||||
Integer lent = wordRanking.getUserName().length();
|
||||
wordRanking.setUserName(lent >= 20 ? wordRanking.getUserName().substring(0,5)+"...."+wordRanking.getUserName().substring(lent-5,lent) : wordRanking.getUserName());
|
||||
if(tMemberRecord.getReferId() != null && tMemberRecord.getReferId() != 0){
|
||||
tMemberRecord = dslContext.select(T_MEMBER.ACCOUNT,T_MEMBER.TWITTER_USER_NAME).from(T_MEMBER).where(T_MEMBER.ID.eq(tMemberRecord.getReferId())).fetchAnyInto(TMemberRecord.class);
|
||||
wordRanking.setSuperior(tMemberRecord.getTwitterName() == null ? tMemberRecord.getAccount() : tMemberRecord.getTwitterName());
|
||||
lent = wordRanking.getSuperior().length();
|
||||
wordRanking.setSuperior(lent >= 20 ? wordRanking.getSuperior().substring(0,5)+"...."+wordRanking.getSuperior().substring(lent-5,lent) : wordRanking.getSuperior());
|
||||
}
|
||||
wordRanking.setAmount(new BigDecimal(wordRanking.getAmount()).stripTrailingZeros().toPlainString());
|
||||
}
|
||||
|
||||
List<ActivityStatisticsRecord> walletList = dslContext.selectFrom(ACTIVITY_STATISTICS)
|
||||
.orderBy(ACTIVITY_STATISTICS.AMOUNT.desc(),ACTIVITY_STATISTICS.ID).limit(req.getOffset(),req.getSize())
|
||||
.fetchInto(ActivityStatisticsRecord.class);
|
||||
|
||||
if(walletList == null || walletList.size() == 0){
|
||||
return wordRanking;
|
||||
}
|
||||
|
||||
Set<String> addressSet = new HashSet<>();
|
||||
walletList.forEach(l -> {
|
||||
addressSet.add(l.getAddress());
|
||||
});
|
||||
|
||||
List<RankingVo> rankingVos = activityMapper.findRankingVoList(addressSet);
|
||||
Map<String,RankingVo> map = new HashMap<>();
|
||||
rankingVos.forEach(l -> map.put(l.getAddress(),l));
|
||||
List<RankingVo> list = new ArrayList<>();
|
||||
for (ActivityStatisticsRecord record : walletList){
|
||||
RankingVo rankingVo = new RankingVo();
|
||||
rankingVo.setAddress(record.getAddress());
|
||||
rankingVo.setAmount(record.getAmount());
|
||||
RankingVo vo = map.get(record.getAddress());
|
||||
if(vo == null){
|
||||
continue;
|
||||
}
|
||||
Integer lent = vo.getUserName().length();
|
||||
rankingVo.setUserName(lent >= 20 ? vo.getUserName().substring(0,5)+"...."+vo.getUserName().substring(lent-5,lent) : vo.getUserName());
|
||||
rankingVo.setUserImg(vo.getUserImg());
|
||||
if(!StringUtils.isBlank(vo.getSuperior())){
|
||||
lent = vo.getSuperior().length();
|
||||
rankingVo.setSuperior(lent >= 20 ? vo.getSuperior().substring(0,5)+"...."+vo.getSuperior().substring(lent-5,lent) : vo.getSuperior());
|
||||
}
|
||||
list.add(rankingVo);
|
||||
}
|
||||
wordRanking.setRankingVos(list);
|
||||
return wordRanking;
|
||||
}
|
||||
|
||||
public static String generateRandomString(int length) {
|
||||
Random random = new Random();
|
||||
StringBuilder stringBuilder = new StringBuilder(length);
|
||||
for (int i = 0; i < length; i++) {
|
||||
int randomIndex = random.nextInt(CHARACTERS.length());
|
||||
char randomChar = CHARACTERS.charAt(randomIndex);
|
||||
stringBuilder.append(randomChar);
|
||||
}
|
||||
return stringBuilder.toString();
|
||||
}
|
||||
|
||||
public void getActivityLog(String address) {
|
||||
ActivityLogRecord activityLogRecord = dslContext.selectFrom(ACTIVITY_LOG).where(ACTIVITY_LOG.ADDRESS.eq(address)
|
||||
.and(ACTIVITY_LOG.TYPE.eq(1)).and(ACTIVITY_LOG.CONFIG_TYPE.eq(8))).fetchAny();
|
||||
if(activityLogRecord != null){
|
||||
//增加用户资产统计
|
||||
dslContext.update(ACTIVITY_STATISTICS).set(ACTIVITY_STATISTICS.AMOUNT,ACTIVITY_STATISTICS.AMOUNT.add(activityLogRecord.getAmount())).where(ACTIVITY_STATISTICS.ADDRESS.eq(address)).execute();
|
||||
dslContext.update(ACTIVITY_STATISTICS).set(ACTIVITY_STATISTICS.AMOUNT,ACTIVITY_STATISTICS.AMOUNT.add(activityLogRecord.getSuperiorAmount())).where(ACTIVITY_STATISTICS.ADDRESS.eq(activityLogRecord.getSuperiorAddress())).execute();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
package com.alive.server.service;
|
||||
|
||||
import com.alive.server.web3.ContractEventHandle;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.web3j.abi.EventEncoder;
|
||||
import org.web3j.protocol.core.methods.response.EthLog;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
public class AirTokenService implements ContractEventHandle {
|
||||
|
||||
final String TRANSFER_TOPIC = EventEncoder.buildEventSignature("Transfer(address,address,uint256)");
|
||||
|
||||
final String BUY_ROOS_SUCCESS = EventEncoder.buildEventSignature("BuyRoosSuccess(address,uint256,address,uint256,uint256,uint256[])");
|
||||
|
||||
final String BRIGADETOL2 = EventEncoder.buildEventSignature("BrigadeToL2(uint256,address)");
|
||||
|
||||
final String PAYMENTSUCCESS = EventEncoder.buildEventSignature("PaymentSuccess(address,uint256,uint256)");
|
||||
|
||||
|
||||
@Override
|
||||
public String handle(EthLog.LogObject logObject, List<String> dataList) {
|
||||
if (logObject.getTopics().get(0).equalsIgnoreCase(TRANSFER_TOPIC)) {
|
||||
return "Transfer";
|
||||
}else if(logObject.getTopics().get(0).equalsIgnoreCase(BUY_ROOS_SUCCESS)){
|
||||
return "BuyRoosSuccess";
|
||||
}else if(logObject.getTopics().get(0).equalsIgnoreCase(BRIGADETOL2)){
|
||||
return "BrigadeToL2";
|
||||
}else if(logObject.getTopics().get(0).equalsIgnoreCase(PAYMENTSUCCESS)){
|
||||
return "PaymentSuccess";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
package com.alive.server.service;
|
||||
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.*;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
/**
|
||||
* 阿里快递查询
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class AliDeliverService {
|
||||
|
||||
//https://market.aliyun.com/products/57126001/cmapi023201.html
|
||||
private static final String URL_FORMAT = "https://wdexpress.market.alicloudapi.com/gxali?n=";
|
||||
|
||||
private static final String APP_CODE = "APPCODE fc28426b30bc4cd39e139efe6cd099ca";
|
||||
|
||||
@Autowired
|
||||
private RestTemplate restTemplate;
|
||||
|
||||
public JSONObject expressInfo(String expressNo, String recPhone) {
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
|
||||
headers.add("Authorization", APP_CODE);
|
||||
|
||||
HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(headers);
|
||||
|
||||
String url = URL_FORMAT + expressNo;
|
||||
ResponseEntity<JSONObject> responseEntity = restTemplate.exchange(url, HttpMethod.GET, requestEntity, JSONObject.class);
|
||||
JSONObject jsonObject = responseEntity.getBody();
|
||||
Assert.notNull(jsonObject, "暂无物流信息");
|
||||
|
||||
//-1:单号或快递公司代码错误, 0:暂无轨迹,1:快递收件,2:在途中,3:签收,4:问题件 5.疑难件 6.退件签收
|
||||
Integer state = jsonObject.getInteger("State");
|
||||
String reason = jsonObject.getString("Reason");
|
||||
Assert.isTrue(state >= 0, reason);
|
||||
|
||||
//倒转物流日志
|
||||
JSONArray traces = jsonObject.getJSONArray("Traces");
|
||||
JSONArray newTraces = new JSONArray();
|
||||
int size = traces.size();
|
||||
for (int i = size - 1; i >= 0; i--) {
|
||||
newTraces.add(traces.get(i));
|
||||
}
|
||||
jsonObject.put("Traces", newTraces);
|
||||
return jsonObject;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
package com.alive.server.service;
|
||||
|
||||
import com.aliyun.dysmsapi20170525.Client;
|
||||
import com.aliyun.dysmsapi20170525.models.SendSmsRequest;
|
||||
import com.aliyun.dysmsapi20170525.models.SendSmsResponse;
|
||||
import com.aliyun.tea.TeaException;
|
||||
import com.aliyun.teaopenapi.models.Config;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* 阿里大鱼短信
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class AliDySmsService {
|
||||
|
||||
private static final String accessKeyId = "LTAI5t8jJ56kxGVZxNf4Ph38";
|
||||
private static final String accessKeySecret = "EgkRHJduyex5Ph0V9PwqhmsQsDJoGZ";
|
||||
private static final String signName = "官酝和合";
|
||||
private static final String templateCode = "SMS_223543777";
|
||||
private static final String endPoint = "dysmsapi.aliyuncs.com";
|
||||
|
||||
private static final Client client;
|
||||
|
||||
static {
|
||||
Config config = new com.aliyun.teaopenapi.models.Config()
|
||||
.setAccessKeyId(accessKeyId)
|
||||
.setAccessKeySecret(accessKeySecret);
|
||||
config.endpoint = endPoint;
|
||||
try {
|
||||
client = new Client(config);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public void sendSms(String mobile, String code) {
|
||||
SendSmsRequest sendSmsRequest = new SendSmsRequest()
|
||||
.setPhoneNumbers(mobile)
|
||||
.setSignName(signName)
|
||||
.setTemplateCode(templateCode)
|
||||
.setTemplateParam("{\"code\":\"" + code + "\"}");
|
||||
|
||||
try {
|
||||
SendSmsResponse response = client.sendSms(sendSmsRequest);
|
||||
log.info("SendDySms {} - {}: {}", mobile, code, response.body.code);
|
||||
} catch (TeaException error) {
|
||||
com.aliyun.teautil.Common.assertAsString(error.message);
|
||||
} catch (Exception _error) {
|
||||
TeaException error = new TeaException(_error.getMessage(), _error);
|
||||
com.aliyun.teautil.Common.assertAsString(error.message);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,268 @@
|
|||
package com.alive.server.service;
|
||||
|
||||
import com.alive.commons.util.RedisUtil;
|
||||
import com.alive.db.entity.NodeBuyLog;
|
||||
import com.alive.db.entity.Vo.TransactionDataVo;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.web3j.protocol.Web3j;
|
||||
import org.web3j.protocol.core.DefaultBlockParameter;
|
||||
import org.web3j.protocol.core.methods.request.EthFilter;
|
||||
import org.web3j.protocol.core.methods.response.EthLog;
|
||||
import org.web3j.protocol.http.HttpService;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
public class BscTimingService {
|
||||
|
||||
@Autowired
|
||||
private AirTokenService airTokenService;
|
||||
|
||||
@Autowired
|
||||
private BtcBuyService btcBuyService;
|
||||
|
||||
@Autowired
|
||||
private NodeBuyLogService nodeBuyLogService;
|
||||
|
||||
@Autowired
|
||||
private ChainLogService chainLogService;
|
||||
|
||||
@Autowired
|
||||
private ActivityService activityService;
|
||||
|
||||
private Web3j bscWsWeb3j;
|
||||
|
||||
/**
|
||||
* 初始化扫描
|
||||
*/
|
||||
private boolean initializeScan = true;
|
||||
|
||||
/**
|
||||
* socket节点
|
||||
*/
|
||||
@Value("${com.alive.chainWsUrl}")
|
||||
private String chainWsUrl;
|
||||
|
||||
/**
|
||||
* 合约地址
|
||||
*/
|
||||
@Value("${com.alive.contractUrl}")
|
||||
private String contractUrl;
|
||||
|
||||
public Web3j getBscWsWeb3j() {
|
||||
if(bscWsWeb3j == null){
|
||||
bscWsWeb3j = Web3j.build(new HttpService(chainWsUrl));
|
||||
}
|
||||
return bscWsWeb3j;
|
||||
}
|
||||
|
||||
/**
|
||||
* 需要同步日志的合约
|
||||
* @return
|
||||
*/
|
||||
private List<String> getAddresses() {
|
||||
return Arrays.asList(contractUrl);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取初始块任务,需要注意控制时间,防止链上限制调用
|
||||
*/
|
||||
public void printLogTask() {
|
||||
String scannedBlockStr = RedisUtil.get("USDT:scannedBlock");
|
||||
if (scannedBlockStr == null || scannedBlockStr.isEmpty()) {
|
||||
log.error(">>> 无已扫描数据,从20000块前开始");
|
||||
BigInteger latestBlock = new BigInteger(RedisUtil.get("USDT:latestBlock"));
|
||||
scannedBlockStr = latestBlock.subtract(BigInteger.valueOf(20000)).toString();
|
||||
RedisUtil.set("USDT:scannedBlock", scannedBlockStr);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取最新块
|
||||
*/
|
||||
public void latestBlockTask() throws IOException {
|
||||
BigInteger latestBlock = this.getBscWsWeb3j().ethBlockNumber().send().getBlockNumber();
|
||||
RedisUtil.set("USDT:latestBlock", latestBlock.toString());
|
||||
}
|
||||
|
||||
private List<EthLog.LogResult> scanBlock(BigInteger startBlock, BigInteger endBlock) {
|
||||
EthFilter filter = new EthFilter(DefaultBlockParameter.valueOf(startBlock),
|
||||
DefaultBlockParameter.valueOf(endBlock),
|
||||
this.getAddresses());
|
||||
EthLog send = null;
|
||||
try {
|
||||
send = this.getBscWsWeb3j().ethGetLogs(filter).send();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
throw new RuntimeException(e.getMessage());
|
||||
}
|
||||
if(send.getError() != null && send.getError().getMessage() != null){
|
||||
log.info("扫描块失败(检查节点是否被限制) out {} ,{}, {}", startBlock, endBlock, send.getError().getMessage());
|
||||
return null;
|
||||
}
|
||||
return send.getLogs();
|
||||
}
|
||||
|
||||
/**
|
||||
* 此方法频繁调用会被限制频率
|
||||
* 此方法弥补订阅停止或者订阅漏掉区块补救措施
|
||||
*/
|
||||
public void bscScanTask() {
|
||||
//获取最新块
|
||||
try {
|
||||
this.latestBlockTask();
|
||||
this.printLogTask();
|
||||
} catch (IOException e) {
|
||||
}
|
||||
BigInteger scannedBlock = new BigInteger(RedisUtil.get("USDT:scannedBlock"));
|
||||
BigInteger latestBlock = new BigInteger(RedisUtil.get("USDT:latestBlock"));
|
||||
BigInteger offset;
|
||||
int times = 0;
|
||||
if(initializeScan){
|
||||
//项目重启,扫描前60个区块
|
||||
scannedBlock = scannedBlock.subtract(new BigInteger("60"));
|
||||
initializeScan = false;
|
||||
}
|
||||
while (latestBlock.subtract(scannedBlock).longValue() > 2 && times++ < 60) {
|
||||
if (latestBlock.longValue() - scannedBlock.longValue() > 10000) {
|
||||
offset = BigInteger.valueOf(500);
|
||||
} else if (latestBlock.longValue() - scannedBlock.longValue() > 1000) {
|
||||
offset = BigInteger.valueOf(100);
|
||||
} else if (latestBlock.longValue() - scannedBlock.longValue() > 100) {
|
||||
offset = BigInteger.valueOf(50);
|
||||
} else if (latestBlock.longValue() - scannedBlock.longValue() > 10) {
|
||||
offset = BigInteger.valueOf(9);
|
||||
} else if (latestBlock.longValue() - scannedBlock.longValue() > 4) {
|
||||
offset = BigInteger.valueOf(3);
|
||||
} else {
|
||||
offset = BigInteger.valueOf(1);
|
||||
}
|
||||
|
||||
if (latestBlock.subtract(scannedBlock).longValue() < offset.longValue()) {
|
||||
break;
|
||||
}
|
||||
List<EthLog.LogResult> resp = this.scanBlock(scannedBlock.add(BigInteger.ONE), scannedBlock.add(offset));
|
||||
if(resp == null){
|
||||
return;
|
||||
}
|
||||
if(resp != null && resp.size() > 0){
|
||||
for (EthLog.LogResult logItem : resp) {
|
||||
this.handleLogEvent((EthLog.LogObject) logItem.get());
|
||||
}
|
||||
}
|
||||
scannedBlock = scannedBlock.add(offset);
|
||||
RedisUtil.set("USDT:scannedBlock", scannedBlock.toString());
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized void handleLogEvent(EthLog.LogObject logObject) {
|
||||
if(RedisUtil.get(logObject.getBlockHash()) != null){
|
||||
//重复Hash,不予处理
|
||||
return;
|
||||
}
|
||||
//重复Hash10分钟过期
|
||||
RedisUtil.setEx(logObject.getBlockHash(),"1",60 * 10);
|
||||
log.info("监听到数据HASH:{},块号:{},交易hash:{}",logObject.getBlockHash(),logObject.getBlockNumber(),logObject.getTransactionHash());
|
||||
String data = logObject.getData().substring(2);
|
||||
List<String> dataList = new ArrayList<>(data.length() / 64);
|
||||
//获取事件名称
|
||||
String even = airTokenService.handle(logObject, dataList);
|
||||
String date = logObject.getData().substring(2,logObject.getData().length());
|
||||
//保存事件
|
||||
chainLogService.addChainLog(logObject.getBlockHash(),logObject.getBlockNumber(),logObject.getTransactionHash(),even,date);
|
||||
if(even != null && even.equals("BuyRoosSuccess")){
|
||||
//我的支付地址
|
||||
String address = this.getValue(date,0,true).toLowerCase();
|
||||
//我的付款金额
|
||||
BigDecimal amount = new BigDecimal(this.getValue(date,1,false));
|
||||
//上级地址
|
||||
String teamAddress = this.getValue(date,2,true).toLowerCase();
|
||||
//上级奖励金额
|
||||
BigDecimal teamAmount = new BigDecimal(this.getValue(date,3,false));
|
||||
//订单编号
|
||||
String orderNumber = this.getValue(date,4,false);
|
||||
//NFT数量
|
||||
String nftNUmber = this.getValue(date,6,false);
|
||||
Integer number = Integer.parseInt(nftNUmber);
|
||||
List<Integer> nftIds = new ArrayList<>();
|
||||
for (int i = 7; i < (7 + number); i++) {
|
||||
//NFT的ID
|
||||
String nftId = this.getValue(date,i,false);
|
||||
if(nftId == null){
|
||||
break;
|
||||
}
|
||||
nftIds.add(Integer.parseInt(nftId));
|
||||
}
|
||||
NodeBuyLog log = nodeBuyLogService.findNodeSubscribeByOrderNumber(orderNumber);
|
||||
if(log == null){
|
||||
return;
|
||||
}
|
||||
log.setHash(logObject.getBlockHash());
|
||||
TransactionDataVo transactionDataVo = new TransactionDataVo();
|
||||
transactionDataVo.setFrom(address);
|
||||
transactionDataVo.setPayAmount(amount);
|
||||
transactionDataVo.setNftNumber(number);
|
||||
transactionDataVo.setNftIds(nftIds);
|
||||
transactionDataVo.setTeamAddress(teamAddress);
|
||||
transactionDataVo.setTeamAmount(teamAmount);
|
||||
transactionDataVo.setStatus(1);
|
||||
btcBuyService.addNft(log,transactionDataVo);
|
||||
}else if(even != null && even.equals("BrigadeToL2")){
|
||||
//我的支付地址
|
||||
String address = this.getValue(date,0,true).toLowerCase();
|
||||
//查询用户是否有未完成的任务
|
||||
activityService.getActivityLog(address);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 查询日志里面加indexed的内容
|
||||
* @param topList 日志内容
|
||||
* @param code 查询第几个
|
||||
* @return
|
||||
*/
|
||||
public BigInteger getNmber(List<String> topList,Integer code){
|
||||
String ret = topList.get(code);
|
||||
ret = ret.substring(2,ret.length());
|
||||
//16进制转10进制
|
||||
return new BigInteger(ret, 16);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取没有加indexed的内容
|
||||
* @param date 拆分的参数
|
||||
* @param code 取的位数
|
||||
* @param address 是否返回地址
|
||||
* @return
|
||||
*/
|
||||
public String getValue(String date, Integer code, Boolean address){
|
||||
int number = 64;
|
||||
if(code == 0){
|
||||
date = date.substring(0,number);
|
||||
}else{
|
||||
code = number * code;
|
||||
date = date.substring(code,code+number);
|
||||
}
|
||||
if(date == null){
|
||||
return null;
|
||||
}
|
||||
if(address){
|
||||
return "0x"+date.substring(24,date.length());
|
||||
}else{
|
||||
return new BigInteger(date, 16).toString();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,158 @@
|
|||
package com.alive.server.service;
|
||||
|
||||
import com.alive.commons.util.RedisUtil;
|
||||
import com.alive.db.entity.NodeBuyLog;
|
||||
import com.alive.db.entity.Vo.TransactionDataVo;
|
||||
import io.reactivex.Flowable;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.web3j.protocol.core.methods.response.EthLog;
|
||||
import org.web3j.protocol.core.methods.response.Log;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
/**
|
||||
* 监听同步事件
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class BscWsService{
|
||||
|
||||
@Autowired
|
||||
private AirTokenService airTokenService;
|
||||
|
||||
@Autowired
|
||||
private BtcBuyService btcBuyService;
|
||||
|
||||
@Autowired
|
||||
private NodeBuyLogService nodeBuyLogService;
|
||||
|
||||
@Autowired
|
||||
private ChainLogService chainLogService;
|
||||
|
||||
@Autowired
|
||||
private ActivityService activityService;
|
||||
|
||||
|
||||
/**
|
||||
* 定义线程数,多少个线程同步socket
|
||||
*/
|
||||
ExecutorService executorService = Executors.newFixedThreadPool(2);
|
||||
|
||||
public void wsExec(Flowable<Log> flowable){
|
||||
flowable.subscribe(log -> {
|
||||
if(log != null){
|
||||
executorService.execute(() -> handleLogEvent((EthLog.LogObject) log));
|
||||
}
|
||||
},throwable -> {
|
||||
System.out.printf("错误-------"+ throwable.getMessage());
|
||||
});
|
||||
}
|
||||
|
||||
private synchronized void handleLogEvent(EthLog.LogObject logObject) {
|
||||
if(RedisUtil.get(logObject.getBlockHash()) != null){
|
||||
//重复Hash,不予处理
|
||||
return;
|
||||
}
|
||||
//重复Hash10分钟过期
|
||||
RedisUtil.setEx(logObject.getBlockHash(),"1",60 * 10);
|
||||
log.info("监听到数据HASH:{},块号:{},交易hash:{}",logObject.getBlockHash(),logObject.getBlockNumber(),logObject.getTransactionHash());
|
||||
String data = logObject.getData().substring(2);
|
||||
List<String> dataList = new ArrayList<>(data.length() / 64);
|
||||
//获取事件名称
|
||||
String even = airTokenService.handle(logObject, dataList);
|
||||
String date = logObject.getData().substring(2,logObject.getData().length());
|
||||
//保存事件
|
||||
chainLogService.addChainLog(logObject.getBlockHash(),logObject.getBlockNumber(),logObject.getTransactionHash(),even,date);
|
||||
if(even != null && even.equals("BuyRoosSuccess")){
|
||||
//我的支付地址
|
||||
String address = this.getValue(date,0,true).toLowerCase();
|
||||
//我的付款金额
|
||||
BigDecimal amount = new BigDecimal(this.getValue(date,1,false));
|
||||
//上级地址
|
||||
String teamAddress = this.getValue(date,2,true).toLowerCase();
|
||||
//上级奖励金额
|
||||
BigDecimal teamAmount = new BigDecimal(this.getValue(date,3,false));
|
||||
//订单编号
|
||||
String orderNumber = this.getValue(date,4,false);
|
||||
//NFT数量
|
||||
String nftNUmber = this.getValue(date,6,false);
|
||||
Integer number = Integer.parseInt(nftNUmber);
|
||||
List<Integer> nftIds = new ArrayList<>();
|
||||
for (int i = 7; i < (7 + number); i++) {
|
||||
//NFT的ID
|
||||
String nftId = this.getValue(date,i,false);
|
||||
if(nftId == null){
|
||||
break;
|
||||
}
|
||||
nftIds.add(Integer.parseInt(nftId));
|
||||
}
|
||||
NodeBuyLog log = nodeBuyLogService.findNodeSubscribeByOrderNumber(orderNumber);
|
||||
if(log == null){
|
||||
return;
|
||||
}
|
||||
log.setHash(logObject.getBlockHash());
|
||||
TransactionDataVo transactionDataVo = new TransactionDataVo();
|
||||
transactionDataVo.setFrom(address);
|
||||
transactionDataVo.setPayAmount(amount);
|
||||
transactionDataVo.setNftNumber(number);
|
||||
transactionDataVo.setNftIds(nftIds);
|
||||
transactionDataVo.setTeamAddress(teamAddress);
|
||||
transactionDataVo.setTeamAmount(teamAmount);
|
||||
transactionDataVo.setStatus(1);
|
||||
btcBuyService.addNft(log,transactionDataVo);
|
||||
}else if(even != null && even.equals("BrigadeToL2")){
|
||||
//我的支付地址
|
||||
String address = this.getValue(date,0,true).toLowerCase();
|
||||
//查询用户是否有未完成的任务
|
||||
activityService.getActivityLog(address);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 查询日志里面加indexed的内容
|
||||
* @param topList 日志内容
|
||||
* @param code 查询第几个
|
||||
* @return
|
||||
*/
|
||||
public BigInteger getNmber(List<String> topList,Integer code){
|
||||
String ret = topList.get(code);
|
||||
ret = ret.substring(2,ret.length());
|
||||
//16进制转10进制
|
||||
return new BigInteger(ret, 16);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取没有加indexed的内容
|
||||
* @param date 拆分的参数
|
||||
* @param code 取的位数
|
||||
* @param address 是否返回地址
|
||||
* @return
|
||||
*/
|
||||
public String getValue(String date, Integer code, Boolean address){
|
||||
int number = 64;
|
||||
if(code == 0){
|
||||
date = date.substring(0,number);
|
||||
}else{
|
||||
code = number * code;
|
||||
date = date.substring(code,code+number);
|
||||
}
|
||||
if(date == null){
|
||||
return null;
|
||||
}
|
||||
if(address){
|
||||
return "0x"+date.substring(24,date.length());
|
||||
}else{
|
||||
return new BigInteger(date, 16).toString();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,231 @@
|
|||
package com.alive.server.service;
|
||||
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.alive.commons.config.BaseComponent;
|
||||
import com.alive.commons.util.DateUtils;
|
||||
import com.alive.commons.util.HttpUtils;
|
||||
import com.alive.commons.util.RedisUtil;
|
||||
import com.alive.db.entity.NodeBuyLog;
|
||||
import com.alive.db.entity.Vo.TransactionDataVo;
|
||||
import com.alive.db.jooq.tables.records.NodeRecord;
|
||||
import com.alive.db.mapper.NodeSettingMapper;
|
||||
import com.alive.server.web3.Web3jServer;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.io.IOException;
|
||||
import java.math.BigDecimal;
|
||||
import java.sql.Timestamp;
|
||||
import java.util.List;
|
||||
|
||||
import static com.alive.db.jooq.Tables.NODE;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author HayDen
|
||||
* @date 2024-01-09
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class BtcBuyService extends BaseComponent
|
||||
{
|
||||
@Autowired
|
||||
private NodeBuyLogService nodeBuyLogService;
|
||||
|
||||
@Autowired
|
||||
private NodeNftConfigService nodeNftConfigService;
|
||||
|
||||
@Resource
|
||||
private NodeSettingMapper nodeSettingMapper;
|
||||
|
||||
@Autowired
|
||||
private Web3jServer web3jServer;
|
||||
|
||||
/**
|
||||
* 检查是否支付成功
|
||||
*/
|
||||
public void exec() {
|
||||
List<NodeBuyLog> nodeSubscribes = nodeBuyLogService.selectNodeSubscribeList(new NodeBuyLog().setStatus(1));
|
||||
if(nodeSubscribes != null && nodeSubscribes.size() > 0){
|
||||
for (NodeBuyLog nodeSubscribe : nodeSubscribes){
|
||||
if(DateUtils.addMinute(nodeSubscribe.getCreateTime(),30).getTime() < System.currentTimeMillis()){
|
||||
nodeSubscribe.setStatus(4);
|
||||
nodeSubscribe.setIllustrate("订单创建超过30分钟未支付");
|
||||
nodeBuyLogService.updateOrAddNodeSubscribe(nodeSubscribe);
|
||||
}
|
||||
}
|
||||
}
|
||||
nodeSubscribes = nodeBuyLogService.selectNodeSubscribeList(new NodeBuyLog().setStatus(2));
|
||||
for (NodeBuyLog nodeSubscribe : nodeSubscribes){
|
||||
log.info("开始确认链上用户购买情况,订单ID:{}---------------------------------",nodeSubscribe.getId());
|
||||
//通过hash查询链上数据
|
||||
TransactionDataVo transactionDataVo = null;
|
||||
try {
|
||||
transactionDataVo = web3jServer.getEthLogsByHash(nodeSubscribe.getHash());
|
||||
} catch (IOException e) {
|
||||
RedisUtil.setEx(nodeSubscribe.getHash(),"0",30);
|
||||
nodeSubscribe.setIllustrate("订单hash数据异常");
|
||||
nodeSubscribe.setStatus(4);
|
||||
nodeBuyLogService.updateOrAddNodeSubscribe(nodeSubscribe);
|
||||
log.info("订单确认失败:{}---------------------------------",nodeSubscribe.getId());
|
||||
continue;
|
||||
}
|
||||
if(transactionDataVo == null){
|
||||
continue;
|
||||
}
|
||||
this.addNft(nodeSubscribe,transactionDataVo);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 铸造NFT
|
||||
* @param nodeSubscribe 订单信息
|
||||
* @param transactionDataVo 铸造链上信息
|
||||
*/
|
||||
public void addNft(NodeBuyLog nodeSubscribe,TransactionDataVo transactionDataVo){
|
||||
//订单与链上数据对比
|
||||
this.dataVerify(nodeSubscribe,transactionDataVo);
|
||||
log.info("本次订单数据确认结果是:{}---------------------------------",nodeSubscribe.getStatus());
|
||||
String nftIds = "";
|
||||
if(nodeSubscribe.getStatus() == 3){
|
||||
for (Integer nftId : transactionDataVo.getNftIds()){
|
||||
nftIds += "#"+nftId+" ";
|
||||
//支付成功
|
||||
NodeRecord nodeRecord = dslContext.newRecord(NODE);
|
||||
nodeRecord.setId(nftId);
|
||||
nodeRecord.setNodeSettingId(nodeSubscribe.getNodeSettingId());
|
||||
nodeRecord.setBuyCoin(nodeSubscribe.getPayCoin());
|
||||
nodeRecord.setBuyAmount(nodeSubscribe.getBuyAmount().divide(new BigDecimal(nodeSubscribe.getBuyCount()),4,BigDecimal.ROUND_HALF_UP));
|
||||
nodeRecord.setBuyNumber(1);
|
||||
nodeRecord.setNodeName(nodeSubscribe.getNodeName());
|
||||
nodeRecord.setConfirmTime(new Timestamp(System.currentTimeMillis()));
|
||||
nodeRecord.setUserId(nodeSubscribe.getUserId());
|
||||
nodeRecord.setOrderNumber(nodeSubscribe.getOrderNumber());
|
||||
nodeRecord.store();
|
||||
}
|
||||
//开始给上级发放奖励
|
||||
nodeNftConfigService.reward(nodeSubscribe);
|
||||
//减少库存
|
||||
nodeSettingMapper.addInventory(nodeSubscribe.getBuyCount(),nodeSubscribe.getNodeSettingId(),nodeSubscribe.getBuyAmount());
|
||||
}
|
||||
if(nodeSubscribe.getStatus() != 2){
|
||||
nodeBuyLogService.updateOrAddNodeSubscribe(nodeSubscribe);
|
||||
}
|
||||
//订单超过2小时无法确认,直接失败处理
|
||||
if(nodeSubscribe.getStatus() == 2 && DateUtils.addMinute(nodeSubscribe.getCreateTime(),30).getTime() < System.currentTimeMillis()){
|
||||
nodeSubscribe.setStatus(4);
|
||||
nodeSubscribe.setIllustrate("订单链上确认超过30分钟,直接取消");
|
||||
nodeBuyLogService.updateOrAddNodeSubscribe(nodeSubscribe);
|
||||
}
|
||||
if(nodeSubscribe.getStatus().equals(4) || nodeSubscribe.getStatus().equals(3)){
|
||||
RedisUtil.setEx(nodeSubscribe.getHash(),nodeSubscribe.getStatus().equals(4) ? "0" : nftIds,30);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 开始对比链上数据是否正确
|
||||
* @param nodeSubscribe
|
||||
* @param transactionDataVo
|
||||
*/
|
||||
public void dataVerify(NodeBuyLog nodeSubscribe,TransactionDataVo transactionDataVo){
|
||||
BigDecimal limit = new BigDecimal("1000000");
|
||||
transactionDataVo.setTeamAmount(transactionDataVo.getTeamAmount().divide(limit));
|
||||
transactionDataVo.setPayAmount(transactionDataVo.getPayAmount().divide(limit));
|
||||
String address0x = "0x0000000000000000000000000000000000000000";
|
||||
if(transactionDataVo.getTeamAddress().equals(address0x)){
|
||||
transactionDataVo.setTeamAddress("0");
|
||||
}
|
||||
if(transactionDataVo.getStatus() == null || transactionDataVo.getStatus().equals(-1)){
|
||||
//链上确认中
|
||||
return;
|
||||
}
|
||||
if(transactionDataVo.getStatus().equals(0)){
|
||||
nodeSubscribe.setIllustrate("链上失败");
|
||||
nodeSubscribe.setStatus(4);
|
||||
return;
|
||||
}
|
||||
if(!nodeSubscribe.getTeamAddress().equals("0") && nodeSubscribe.getRebate().compareTo(BigDecimal.ZERO) != 0){
|
||||
if(!transactionDataVo.getTeamAddress().equals("0") && nodeSubscribe.getRebate().compareTo(transactionDataVo.getTeamAmount()) != 0){
|
||||
nodeSubscribe.setIllustrate("上级奖励金额不一致");
|
||||
nodeSubscribe.setStatus(4);
|
||||
return;
|
||||
}
|
||||
if(nodeSubscribe.getTeamAddress().compareTo(transactionDataVo.getTeamAddress()) != 0){
|
||||
nodeSubscribe.setIllustrate("上级地址奖励不一致");
|
||||
nodeSubscribe.setStatus(4);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if(transactionDataVo.getPayAmount().compareTo(nodeSubscribe.getBuyAmount()) != 0){
|
||||
nodeSubscribe.setIllustrate("支付金额不一致");
|
||||
nodeSubscribe.setStatus(4);
|
||||
return;
|
||||
}
|
||||
if(!transactionDataVo.getFrom().equals(nodeSubscribe.getWalletAddress())){
|
||||
nodeSubscribe.setIllustrate("支付地址不一致");
|
||||
nodeSubscribe.setStatus(4);
|
||||
}
|
||||
if(!transactionDataVo.getNftNumber().equals(nodeSubscribe.getBuyCount())){
|
||||
nodeSubscribe.setIllustrate("NFT铸造数量不一致");
|
||||
nodeSubscribe.setStatus(4);
|
||||
}else{
|
||||
nodeSubscribe.setIllustrate("铸造成功");
|
||||
nodeSubscribe.setStatus(3);
|
||||
}
|
||||
}
|
||||
|
||||
public Boolean httpContractByHash(NodeBuyLog nodeSubscribe,BigDecimal scope,String configAddress){
|
||||
if(nodeSubscribe.getHash() == null){
|
||||
nodeSubscribe.setStatus(4);
|
||||
}else{
|
||||
String hash = nodeSubscribe.getHash();
|
||||
String value = HttpUtils.sendGet("https://blockchain.info/rawtx/"+hash);
|
||||
if(StringUtils.isBlank(value)){
|
||||
return true;
|
||||
}
|
||||
JSONObject qu = JSONObject.parseObject(value, JSONObject.class);
|
||||
//获取到交易数据
|
||||
if(qu.get("block_index") == null || qu.get("block_height") == null){
|
||||
//区块未确认
|
||||
return false;
|
||||
}
|
||||
//交易发起数据
|
||||
JSONArray inputs = qu.getJSONArray("inputs");
|
||||
JSONObject inputsValue = inputs.getJSONObject(0).getJSONObject("prev_out");
|
||||
{
|
||||
//出账地址
|
||||
String address = inputsValue.get("addr").toString().toLowerCase();
|
||||
nodeSubscribe.setInputAddress(address);
|
||||
nodeSubscribe.setStatus(3);
|
||||
}
|
||||
{
|
||||
JSONArray out = qu.getJSONArray("out");
|
||||
JSONObject outUser = out.getJSONObject(0);
|
||||
//收款地址
|
||||
String address = outUser.get("addr").toString().toLowerCase();
|
||||
|
||||
//出账金额
|
||||
String inpAmount = outUser.get("value").toString();
|
||||
//放大计算
|
||||
if(new BigDecimal(inpAmount).compareTo(nodeSubscribe.getBuyAmount().multiply(scope)) != 0){
|
||||
nodeSubscribe.setStatus(4);
|
||||
}
|
||||
nodeSubscribe.setOutAddress(address);
|
||||
if(!configAddress.equals(address)){
|
||||
//收款地址不对
|
||||
nodeSubscribe.setStatus(4);
|
||||
}
|
||||
//收款金额
|
||||
//String outAmount = outUser.get("value").toString();
|
||||
//手续费
|
||||
//JSONObject outUserFee = out.getJSONObject(1);
|
||||
//String fee = outUserFee.get("value").toString();
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
package com.alive.server.service;
|
||||
|
||||
import com.alive.db.jooq.tables.records.ChainLogRecord;
|
||||
import org.jooq.DSLContext;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
||||
import static com.alive.db.jooq.Tables.CHAIN_LOG;
|
||||
|
||||
@Service
|
||||
public class ChainLogService
|
||||
{
|
||||
@Autowired
|
||||
private DSLContext dslContext;
|
||||
|
||||
|
||||
public void addChainLog(String hash, BigInteger blockNumber,String transactionHash, String even, String date)
|
||||
{
|
||||
ChainLogRecord chainLogRecord = dslContext.newRecord(CHAIN_LOG);
|
||||
chainLogRecord.setHash(hash);
|
||||
chainLogRecord.setBlockNumber(blockNumber.toString());
|
||||
chainLogRecord.setChainName(even);
|
||||
chainLogRecord.setDataValue(date);
|
||||
chainLogRecord.setTransactionHash(transactionHash);
|
||||
chainLogRecord.store();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
package com.alive.server.service;
|
||||
|
||||
import com.alive.commons.util.RedisUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang.RandomStringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
public class CodeService {
|
||||
|
||||
@Autowired
|
||||
private DingService dingService;
|
||||
|
||||
@Autowired
|
||||
private AliDySmsService aliDySmsService;
|
||||
|
||||
@Value("${spring.profiles.active}")
|
||||
private String env;
|
||||
|
||||
private final static String PRE_FIX_FORMAT = "juxing:chapter:%d:%s";
|
||||
private final static long EXPIRE_TIME = 600;
|
||||
private final static int TYPE = 0;
|
||||
|
||||
public void send(String mobile, int type) {
|
||||
String code = RedisUtil.get(String.format(PRE_FIX_FORMAT, TYPE, mobile));
|
||||
long ttl = -1;
|
||||
if (code != null) {
|
||||
ttl = RedisUtil.ttl(String.format(PRE_FIX_FORMAT, TYPE, mobile));
|
||||
Assert.isTrue(ttl < 500, "发送过于频繁");
|
||||
}
|
||||
if (ttl < 200) {
|
||||
//如果验证码小于200s过期,更换验证码
|
||||
code = RandomStringUtils.random(6, false, true);
|
||||
}
|
||||
RedisUtil.setEx(String.format(PRE_FIX_FORMAT, TYPE, mobile), code, EXPIRE_TIME);
|
||||
log.info("发送验证码:{} - {}", mobile, code);
|
||||
if ("prod".equals(env)) {
|
||||
aliDySmsService.sendSms(mobile, code);
|
||||
return;
|
||||
}
|
||||
String content = "【官酝和合】您的验证码是" + code + "。如非本人操作,请忽略本短信";
|
||||
//dingService.sendMsg(mobile, content);
|
||||
}
|
||||
|
||||
public boolean check(String mobile, int type, String code) {
|
||||
String saved = RedisUtil.get(String.format(PRE_FIX_FORMAT, TYPE, mobile));
|
||||
if (saved == null || code == null) {
|
||||
return false;
|
||||
}
|
||||
if ("000000".equals(code) && !env.equals("prod")) {
|
||||
return true;
|
||||
}
|
||||
return code.equals(saved);
|
||||
}
|
||||
|
||||
public boolean checkAndDel(String mobile, int type, String code) {
|
||||
if (!check(mobile, TYPE, code)) {
|
||||
return false;
|
||||
}
|
||||
del(mobile);
|
||||
return true;
|
||||
}
|
||||
|
||||
public void del(String mobile) {
|
||||
RedisUtil.del(String.format(PRE_FIX_FORMAT, TYPE, mobile));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,464 @@
|
|||
package com.alive.server.service;
|
||||
|
||||
import com.alive.commons.config.BaseComponent;
|
||||
import com.alive.commons.enums.WalletLogTypeEnum;
|
||||
import com.alive.commons.model.BasePageReq;
|
||||
import com.alive.commons.util.*;
|
||||
import com.alive.db.entity.NodeBuyLog;
|
||||
import com.alive.db.entity.Vo.*;
|
||||
import com.alive.db.jooq.tables.pojos.SysConfigPojo;
|
||||
import com.alive.db.jooq.tables.records.*;
|
||||
import com.alive.db.mapper.NodeSettingMapper;
|
||||
import com.alive.db.mapper.PersonalCenterMapper;
|
||||
import com.alive.server.api.account.PayCoinReq;
|
||||
import com.alive.server.api.account.PayNodeSmsReq;
|
||||
import com.alive.server.api.account.TeskReq;
|
||||
import com.alive.server.dto.WalletOperation;
|
||||
import com.alive.server.web3.Web3jServer;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.core.annotation.OrderUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.Assert;
|
||||
import org.web3j.abi.datatypes.Int;
|
||||
import org.web3j.protocol.Web3j;
|
||||
import org.web3j.protocol.core.DefaultBlockParameter;
|
||||
import org.web3j.protocol.core.methods.request.EthFilter;
|
||||
import org.web3j.protocol.core.methods.response.EthLog;
|
||||
import org.web3j.protocol.http.HttpService;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Member;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
import java.sql.Timestamp;
|
||||
import java.util.*;
|
||||
|
||||
import static com.alive.db.jooq.Tables.*;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
public class CrowdfundingService extends BaseComponent {
|
||||
|
||||
@Autowired
|
||||
private MemberService memberService;
|
||||
|
||||
@Autowired
|
||||
private WalletService walletService;
|
||||
|
||||
@Autowired
|
||||
private ChainLogService chainLogService;
|
||||
|
||||
@Autowired
|
||||
private AirTokenService airTokenService;
|
||||
|
||||
/**
|
||||
* 合约地址
|
||||
*/
|
||||
@Value("${com.alive.contractUrl}")
|
||||
private String contractUrl;
|
||||
|
||||
/**
|
||||
* 初始化扫描
|
||||
*/
|
||||
private boolean initializeScan = true;
|
||||
|
||||
@Autowired
|
||||
private Web3jServer web3jServer;
|
||||
|
||||
public Web3j getBscWsWeb3j() {
|
||||
return web3jServer.getWeb3j();
|
||||
}
|
||||
|
||||
/**
|
||||
* 需要同步日志的合约
|
||||
* @return
|
||||
*/
|
||||
private List<String> getAddresses() {
|
||||
return Arrays.asList(contractUrl);
|
||||
}
|
||||
|
||||
|
||||
public Boolean payNodeSms(PayNodeSmsReq req) {
|
||||
int memberId = Integer.parseInt(RequestUtil.getCurrentAccount());
|
||||
PayCoinLogRecord payCoinLogRecord = dslContext.select().from(PAY_COIN_LOG).where(PAY_COIN_LOG.STATUS.eq(1))
|
||||
.and(PAY_COIN_LOG.MEMBER_ID.eq(memberId)).and(PAY_COIN_LOG.ORDER_NUMBER.eq(req.getOrderNumber())).fetchAnyInto(PayCoinLogRecord.class);
|
||||
Assert.isTrue(payCoinLogRecord != null && payCoinLogRecord.getStatus().equals(1), "Order error");
|
||||
if (req.getStatus().equals(2)) {
|
||||
dslContext.update(PAY_COIN_LOG).set(PAY_COIN_LOG.STATUS,4).set(PAY_COIN_LOG.ILLUSTRATE,"取消订单")
|
||||
.where(PAY_COIN_LOG.ID.eq(payCoinLogRecord.getId())).execute();
|
||||
return true;
|
||||
}
|
||||
dslContext.update(PAY_COIN_LOG).set(PAY_COIN_LOG.HASH,req.getHash())
|
||||
.where(PAY_COIN_LOG.ID.eq(payCoinLogRecord.getId())).execute();
|
||||
return true;
|
||||
}
|
||||
|
||||
public PrivatePlacementVo getPrivatePlacement() {
|
||||
PrivatePlacementVo privatePlacementVo = new PrivatePlacementVo();
|
||||
List<CoinConfigRecord> coins = dslContext.select().from(COIN_CONFIG).where(COIN_CONFIG.STATE.eq(1)).fetchInto(CoinConfigRecord.class);
|
||||
if(coins != null && coins.size() > 0){
|
||||
CoinConfigRecord coin = coins.get(0);
|
||||
privatePlacementVo.setUsdtPrice(coin.getUsdtPrice().stripTrailingZeros().toPlainString());
|
||||
privatePlacementVo.setMinNumber(coin.getMinNumber().stripTrailingZeros().toPlainString());
|
||||
privatePlacementVo.setPrivatePlacement(coin.getPrivatePlacement().stripTrailingZeros().toPlainString());
|
||||
privatePlacementVo.setToPrivatePlacement(coin.getToPrivatePlacement().stripTrailingZeros().toPlainString());
|
||||
privatePlacementVo.setCoinId(coin.getId());
|
||||
}
|
||||
if(StringUtils.isBlank(RequestUtil.getToken())){
|
||||
privatePlacementVo.setWordPrivatePlacement("0");
|
||||
privatePlacementVo.setWordAirdrop("0");
|
||||
return privatePlacementVo;
|
||||
}
|
||||
int memberId = Integer.parseInt(RequestUtil.getCurrentAccount());
|
||||
List<TMemberWalletRecord> walletRecords = dslContext.select().from(T_MEMBER_WALLET).where(T_MEMBER_WALLET.MEMBER_ID.eq(memberId)).fetchInto(TMemberWalletRecord.class);
|
||||
for (TMemberWalletRecord memberWalletRecord : walletRecords){
|
||||
if(memberWalletRecord.getCoinId().equals(1)){
|
||||
privatePlacementVo.setWordPrivatePlacement(memberWalletRecord.getBalance().add(memberWalletRecord.getFrozen()).stripTrailingZeros().toPlainString());
|
||||
}else if(memberWalletRecord.getCoinId().equals(2)){
|
||||
privatePlacementVo.setWordAirdrop(memberWalletRecord.getBalance().add(memberWalletRecord.getFrozen()).stripTrailingZeros().toPlainString());
|
||||
}
|
||||
}
|
||||
return privatePlacementVo;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 用户下单
|
||||
* @param req
|
||||
* @return
|
||||
*/
|
||||
public PayCoinVo payOrder(PayCoinReq req) {
|
||||
BigDecimal amount = new BigDecimal(req.getAmount());
|
||||
CoinConfigRecord configRecord = dslContext.select().from(COIN_CONFIG).where(COIN_CONFIG.ID.eq(req.getCoinId())).fetchAnyInto(CoinConfigRecord.class);
|
||||
Assert.isTrue(configRecord != null, "Coin config is null");
|
||||
Assert.isTrue(amount.compareTo(configRecord.getMinNumber()) >= 0 && amount.compareTo(configRecord.getMaxNumber()) <= 0, "Minimum or maximum purchase quantity limits");
|
||||
Assert.isTrue(configRecord.getPrivatePlacement().subtract(configRecord.getToPrivatePlacement()).subtract(amount).compareTo(BigDecimal.ZERO) >= 0, "Insufficient inventory");
|
||||
int memberId = Integer.parseInt(RequestUtil.getCurrentAccount());
|
||||
TMemberRecord tMemberRecord = memberService.fetchOne(memberId);
|
||||
PayCoinLogRecord payCoinLogRecord = dslContext.newRecord(PAY_COIN_LOG);
|
||||
payCoinLogRecord.setMemberId(tMemberRecord.getId());
|
||||
payCoinLogRecord.setAddress(tMemberRecord.getAccount());
|
||||
payCoinLogRecord.setCoinName(configRecord.getCoinName());
|
||||
payCoinLogRecord.setUnitPrice(configRecord.getUsdtPrice());
|
||||
payCoinLogRecord.setAmount(amount);
|
||||
payCoinLogRecord.setPayUsdt(amount.multiply(configRecord.getUsdtPrice()));
|
||||
payCoinLogRecord.setStatus(1);
|
||||
payCoinLogRecord.setOrderNumber(NumberUtil.getUUIDBy16());
|
||||
payCoinLogRecord.setCoinId(configRecord.getId());
|
||||
payCoinLogRecord.setCoinName(configRecord.getCoinName());
|
||||
payCoinLogRecord.store();
|
||||
PayCoinVo payCoinVo = new PayCoinVo();
|
||||
payCoinVo.setOrderNumber(payCoinLogRecord.getOrderNumber());
|
||||
payCoinVo.setUsdtAmount(payCoinLogRecord.getPayUsdt().multiply(new BigDecimal("1000000000000000000")));
|
||||
return payCoinVo;
|
||||
}
|
||||
|
||||
/**
|
||||
* 众筹确认是否支付成功
|
||||
*/
|
||||
public void exec() {
|
||||
List<PayCoinLogRecord> payCoinLogRecords = dslContext.select().from(PAY_COIN_LOG).where(PAY_COIN_LOG.STATUS.eq(1)).fetchInto(PayCoinLogRecord.class);
|
||||
List<PayCoinLogRecord> payCoinLogRecordList = new ArrayList<>();
|
||||
if(payCoinLogRecords != null && payCoinLogRecords.size() > 0){
|
||||
for (PayCoinLogRecord nodeSubscribe : payCoinLogRecords){
|
||||
if(DateUtils.addMinute(nodeSubscribe.getCreateTime(),30).getTime() < System.currentTimeMillis()){
|
||||
dslContext.update(PAY_COIN_LOG).set(PAY_COIN_LOG.STATUS,4).set(PAY_COIN_LOG.ILLUSTRATE,"订单创建超过30分钟未支付")
|
||||
.where(PAY_COIN_LOG.ID.eq(nodeSubscribe.getId())).execute();
|
||||
continue;
|
||||
}
|
||||
payCoinLogRecordList.add(nodeSubscribe);
|
||||
}
|
||||
}
|
||||
for (PayCoinLogRecord payCoinLogRecord : payCoinLogRecordList){
|
||||
if(payCoinLogRecord.getHash() == null){
|
||||
continue;
|
||||
}
|
||||
log.info("开始确认链上用户购买情况,订单ID:{}---------------------------------",payCoinLogRecord.getId());
|
||||
//通过hash查询链上数据
|
||||
PayCoinVo payCoinVo = null;
|
||||
try {
|
||||
payCoinVo = web3jServer.crowdfundingByHash(payCoinLogRecord.getHash());
|
||||
} catch (IOException e) {
|
||||
RedisUtil.setEx(payCoinLogRecord.getHash(),"0",30);
|
||||
dslContext.update(PAY_COIN_LOG).set(PAY_COIN_LOG.STATUS,4).set(PAY_COIN_LOG.ILLUSTRATE,"订单hash数据异常")
|
||||
.where(PAY_COIN_LOG.ID.eq(payCoinLogRecord.getId())).execute();
|
||||
|
||||
log.info("订单确认失败:{}---------------------------------",payCoinLogRecord.getId());
|
||||
continue;
|
||||
}
|
||||
if(payCoinVo == null){
|
||||
continue;
|
||||
}
|
||||
this.addPrivatePlacement(payCoinLogRecord,payCoinVo);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 私募
|
||||
* @param nodeSubscribe 订单信息
|
||||
* @param transactionDataVo 铸造链上信息
|
||||
*/
|
||||
public void addPrivatePlacement(PayCoinLogRecord nodeSubscribe,PayCoinVo transactionDataVo){
|
||||
//订单与链上数据对比
|
||||
this.dataVerify(nodeSubscribe,transactionDataVo);
|
||||
log.info("本次订单数据确认结果是:{}---------------------------------",nodeSubscribe.getStatus());
|
||||
String nftIds = "";
|
||||
if(nodeSubscribe.getStatus() == 3){
|
||||
//入账
|
||||
TMemberWalletRecord walletRecord= walletService.getWallet(nodeSubscribe.getMemberId(), nodeSubscribe.getCoinId());
|
||||
WalletOperation walletOperation = WalletOperation.buildParam(1,walletRecord.getId(), WalletLogTypeEnum.PRIVATE_PLACEMENT,nodeSubscribe.getAmount(),"私募");
|
||||
walletService.operateBalance(walletOperation);
|
||||
//减少库存
|
||||
dslContext.update(COIN_CONFIG).set(COIN_CONFIG.TO_PRIVATE_PLACEMENT,COIN_CONFIG.TO_PRIVATE_PLACEMENT.add(nodeSubscribe.getAmount()))
|
||||
.where(COIN_CONFIG.ID.eq(nodeSubscribe.getCoinId())).execute();
|
||||
}
|
||||
if(nodeSubscribe.getStatus() != 2){
|
||||
dslContext.update(PAY_COIN_LOG).set(PAY_COIN_LOG.STATUS,nodeSubscribe.getStatus()).set(PAY_COIN_LOG.ILLUSTRATE,nodeSubscribe.getIllustrate())
|
||||
.where(PAY_COIN_LOG.ID.eq(nodeSubscribe.getId())).execute();
|
||||
}
|
||||
//订单超过2小时无法确认,直接失败处理
|
||||
if(nodeSubscribe.getStatus() == 2 && DateUtils.addMinute(nodeSubscribe.getCreateTime(),30).getTime() < System.currentTimeMillis()){
|
||||
dslContext.update(PAY_COIN_LOG).set(PAY_COIN_LOG.STATUS,4).set(PAY_COIN_LOG.ILLUSTRATE,"订单链上确认超过30分钟,直接取消")
|
||||
.where(PAY_COIN_LOG.ID.eq(nodeSubscribe.getId())).execute();
|
||||
}
|
||||
if(nodeSubscribe.getStatus().equals(4) || nodeSubscribe.getStatus().equals(3)){
|
||||
RedisUtil.setEx(nodeSubscribe.getHash(),nodeSubscribe.getStatus().equals(4) ? "0" : nftIds,30);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 开始对比链上数据是否正确
|
||||
* @param nodeSubscribe
|
||||
* @param transactionDataVo
|
||||
*/
|
||||
public void dataVerify(PayCoinLogRecord nodeSubscribe,PayCoinVo transactionDataVo){
|
||||
BigDecimal limit = new BigDecimal("1000000000000000000");
|
||||
transactionDataVo.setUsdtAmount(transactionDataVo.getUsdtAmount().divide(limit));
|
||||
if(transactionDataVo.getStatus() == null || transactionDataVo.getStatus().equals(-1)){
|
||||
//链上确认中
|
||||
return;
|
||||
}
|
||||
if(transactionDataVo.getStatus().equals(0)){
|
||||
nodeSubscribe.setIllustrate("链上失败");
|
||||
nodeSubscribe.setStatus(4);
|
||||
return;
|
||||
}
|
||||
if(transactionDataVo.getUsdtAmount().compareTo(nodeSubscribe.getPayUsdt()) != 0){
|
||||
nodeSubscribe.setIllustrate("支付金额不一致");
|
||||
nodeSubscribe.setStatus(4);
|
||||
return;
|
||||
}
|
||||
if(!transactionDataVo.getAddress().equals(nodeSubscribe.getAddress())){
|
||||
nodeSubscribe.setIllustrate("支付地址不一致");
|
||||
nodeSubscribe.setStatus(4);
|
||||
}
|
||||
nodeSubscribe.setIllustrate("成功");
|
||||
nodeSubscribe.setStatus(3);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取初始块任务,需要注意控制时间,防止链上限制调用
|
||||
*/
|
||||
public void printLogTask() {
|
||||
String scannedBlockStr = RedisUtil.get("ALIVE-USDT:scannedBlock");
|
||||
if (scannedBlockStr == null || scannedBlockStr.isEmpty()) {
|
||||
log.error(">>> 无已扫描数据,从20000块前开始");
|
||||
BigInteger latestBlock = new BigInteger(RedisUtil.get("ALIVE-USDT:latestBlock"));
|
||||
scannedBlockStr = latestBlock.subtract(BigInteger.valueOf(20000)).toString();
|
||||
RedisUtil.set("ALIVE-USDT:scannedBlock", scannedBlockStr);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取最新块
|
||||
*/
|
||||
public void latestBlockTask() throws IOException {
|
||||
BigInteger latestBlock = this.getBscWsWeb3j().ethBlockNumber().send().getBlockNumber();
|
||||
RedisUtil.set("ALIVE-USDT:latestBlock", latestBlock.toString());
|
||||
}
|
||||
|
||||
private synchronized List<EthLog.LogResult> scanBlock(BigInteger startBlock, BigInteger endBlock) {
|
||||
EthFilter filter = new EthFilter(DefaultBlockParameter.valueOf(startBlock),
|
||||
DefaultBlockParameter.valueOf(endBlock),
|
||||
this.getAddresses());
|
||||
EthLog send = null;
|
||||
try {
|
||||
send = this.getBscWsWeb3j().ethGetLogs(filter).send();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
throw new RuntimeException(e.getMessage());
|
||||
}
|
||||
if(send.getError() != null && send.getError().getMessage() != null){
|
||||
log.info("扫描块失败(检查节点是否被限制) out {} ,{}, {}", startBlock, endBlock, send.getError().getMessage());
|
||||
return null;
|
||||
}
|
||||
return send.getLogs();
|
||||
}
|
||||
|
||||
/**
|
||||
* 此方法频繁调用会被限制频率
|
||||
* 此方法弥补订阅停止或者订阅漏掉区块补救措施
|
||||
*/
|
||||
public void bscScanTask() {
|
||||
//获取最新块
|
||||
try {
|
||||
this.latestBlockTask();
|
||||
this.printLogTask();
|
||||
} catch (IOException e) {
|
||||
}
|
||||
BigInteger scannedBlock = new BigInteger(RedisUtil.get("ALIVE-USDT:scannedBlock"));
|
||||
BigInteger latestBlock = new BigInteger(RedisUtil.get("ALIVE-USDT:latestBlock"));
|
||||
log.info("=====:{},%%%%%%:{}",scannedBlock,latestBlock);
|
||||
BigInteger offset;
|
||||
int times = 0;
|
||||
if(initializeScan){
|
||||
//项目重启,扫描前60个区块
|
||||
scannedBlock = scannedBlock.subtract(new BigInteger("60"));
|
||||
initializeScan = false;
|
||||
}
|
||||
while (latestBlock.subtract(scannedBlock).longValue() > 2 && times++ < 60) {
|
||||
if (latestBlock.longValue() - scannedBlock.longValue() > 10000) {
|
||||
offset = BigInteger.valueOf(500);
|
||||
} else if (latestBlock.longValue() - scannedBlock.longValue() > 1000) {
|
||||
offset = BigInteger.valueOf(100);
|
||||
} else if (latestBlock.longValue() - scannedBlock.longValue() > 100) {
|
||||
offset = BigInteger.valueOf(50);
|
||||
} else if (latestBlock.longValue() - scannedBlock.longValue() > 10) {
|
||||
offset = BigInteger.valueOf(9);
|
||||
} else if (latestBlock.longValue() - scannedBlock.longValue() > 4) {
|
||||
offset = BigInteger.valueOf(3);
|
||||
} else {
|
||||
offset = BigInteger.valueOf(1);
|
||||
}
|
||||
|
||||
if (latestBlock.subtract(scannedBlock).longValue() < offset.longValue()) {
|
||||
break;
|
||||
}
|
||||
List<EthLog.LogResult> resp = this.scanBlock(scannedBlock.add(BigInteger.ONE), scannedBlock.add(offset));
|
||||
if(resp == null){
|
||||
return;
|
||||
}
|
||||
if(resp != null && resp.size() > 0){
|
||||
for (EthLog.LogResult logItem : resp) {
|
||||
this.handleLogEvent((EthLog.LogObject) logItem.get());
|
||||
}
|
||||
}
|
||||
scannedBlock = scannedBlock.add(offset);
|
||||
RedisUtil.set("ALIVE-USDT:scannedBlock", scannedBlock.toString());
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized void handleLogEvent(EthLog.LogObject logObject) {
|
||||
if(RedisUtil.get(logObject.getBlockHash()) != null){
|
||||
//重复Hash,不予处理
|
||||
return;
|
||||
}
|
||||
//重复Hash10分钟过期
|
||||
RedisUtil.setEx(logObject.getBlockHash(),"1",60 * 10);
|
||||
log.info("监听到数据HASH:{},块号:{},交易hash:{}",logObject.getBlockHash(),logObject.getBlockNumber(),logObject.getTransactionHash());
|
||||
String data = logObject.getData().substring(2);
|
||||
List<String> dataList = new ArrayList<>(data.length() / 64);
|
||||
//获取事件名称
|
||||
String even = airTokenService.handle(logObject, dataList);
|
||||
String date = logObject.getData().substring(2,logObject.getData().length());
|
||||
//保存事件
|
||||
chainLogService.addChainLog(logObject.getBlockHash(),logObject.getBlockNumber(),logObject.getTransactionHash(),even,date);
|
||||
if(even != null && even.equals("PaymentSuccess")){
|
||||
//我的支付地址
|
||||
String address = this.getValue(date,0,true).toLowerCase();
|
||||
//我的付款金额
|
||||
BigDecimal amount = new BigDecimal(this.getValue(date,1,false));
|
||||
//上级地址
|
||||
String orderNumber = this.getValue(date,2,false);
|
||||
PayCoinLogRecord payCoinLogRecord = dslContext.select().from(PAY_COIN_LOG).where(PAY_COIN_LOG.ORDER_NUMBER.eq(orderNumber)).fetchAnyInto(PayCoinLogRecord.class);
|
||||
if(payCoinLogRecord == null){
|
||||
return;
|
||||
}
|
||||
payCoinLogRecord.setHash(logObject.getBlockHash());
|
||||
PayCoinVo payCoinVo = new PayCoinVo();
|
||||
payCoinVo.setAddress(address);
|
||||
payCoinVo.setUsdtAmount(amount);
|
||||
payCoinVo.setOrderNumber(orderNumber);
|
||||
payCoinVo.setStatus(1);
|
||||
this.addPrivatePlacement(payCoinLogRecord,payCoinVo);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 查询日志里面加indexed的内容
|
||||
* @param topList 日志内容
|
||||
* @param code 查询第几个
|
||||
* @return
|
||||
*/
|
||||
public BigInteger getNmber(List<String> topList,Integer code){
|
||||
String ret = topList.get(code);
|
||||
ret = ret.substring(2,ret.length());
|
||||
//16进制转10进制
|
||||
return new BigInteger(ret, 16);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取没有加indexed的内容
|
||||
* @param date 拆分的参数
|
||||
* @param code 取的位数
|
||||
* @param address 是否返回地址
|
||||
* @return
|
||||
*/
|
||||
public String getValue(String date, Integer code, Boolean address){
|
||||
int number = 64;
|
||||
if(code == 0){
|
||||
date = date.substring(0,number);
|
||||
}else{
|
||||
code = number * code;
|
||||
date = date.substring(code,code+number);
|
||||
}
|
||||
if(date == null){
|
||||
return null;
|
||||
}
|
||||
if(address){
|
||||
return "0x"+date.substring(24,date.length());
|
||||
}else{
|
||||
return new BigInteger(date, 16).toString();
|
||||
}
|
||||
}
|
||||
|
||||
public String contractAddress() {
|
||||
SysConfigPojo config = dslContext.select().from(SYS_CONFIG).where(SYS_CONFIG.CONFIG_KEY.eq("PRIVATE_PLACEMENT")).fetchAnyInto(SysConfigPojo.class);
|
||||
return config.getValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* 领取空投
|
||||
* @return
|
||||
*/
|
||||
public Map<String, String> claimTheAirdrop() {
|
||||
Map<String, String> map = new HashMap<>();
|
||||
int memberId = Integer.parseInt(RequestUtil.getCurrentAccount());
|
||||
CoinConfigRecord configRecord = dslContext.select().from(COIN_CONFIG).where(COIN_CONFIG.AIRDROP_NUMBER.gt(BigDecimal.ZERO)).limit(1).fetchAnyInto(CoinConfigRecord.class);
|
||||
Assert.isTrue(configRecord != null, "Claim failed");
|
||||
Integer count = dslContext.selectCount().from(T_MEMBER_WALLET_LOG).where(T_MEMBER_WALLET_LOG.COIN_ID.eq(configRecord.getId())
|
||||
.and(T_MEMBER_WALLET_LOG.MEMBER_ID.eq(memberId)).and(T_MEMBER_WALLET_LOG.OP_TYPE.eq(WalletLogTypeEnum.AIRDROP.getCode()))).fetchAnyInto(Integer.class);
|
||||
Assert.isTrue(count <= 0, "You ve already claimed it");
|
||||
TMemberWalletRecord walletRecord = dslContext.select().from(T_MEMBER_WALLET).where(T_MEMBER_WALLET.COIN_ID.eq(configRecord.getId())
|
||||
.and(T_MEMBER_WALLET.MEMBER_ID.eq(memberId))).fetchAnyInto(TMemberWalletRecord.class);
|
||||
WalletOperation walletOperation = WalletOperation.buildParam(1,walletRecord.getId(), WalletLogTypeEnum.AIRDROP,configRecord.getAirdropNumber(),"空投");
|
||||
walletService.operateBalance(walletOperation);
|
||||
map.put("result","true");
|
||||
return map;
|
||||
}
|
||||
|
||||
public String getAirdropNumber() {
|
||||
CoinConfigRecord configRecord = dslContext.select().from(COIN_CONFIG).where(COIN_CONFIG.AIRDROP_NUMBER.gt(BigDecimal.ZERO)).limit(1).fetchAnyInto(CoinConfigRecord.class);
|
||||
if(configRecord == null){
|
||||
return "0";
|
||||
}
|
||||
return configRecord.getAirdropNumber().stripTrailingZeros().toPlainString();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,82 @@
|
|||
package com.alive.server.service;
|
||||
|
||||
import com.alive.commons.util.ShaUtil;
|
||||
import lombok.Data;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpEntity;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.Map;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
//@Profile({"dev", "test"})
|
||||
public class DingService {
|
||||
|
||||
@Autowired
|
||||
private RestTemplate restTemplate;
|
||||
private final String token = "92c6649e0ab689bf8963fc6102a49b038832aa16ed85e58627c56355434b02d9";
|
||||
|
||||
private final String secret = "SEC941a9e16fc8f5eb20ad9786f84c8226d8831bd9b61d69a06ad8d216a67bb2043";
|
||||
|
||||
//https://oapi.dingtalk.com/robot/send?access_token=a16e52a33b63efd8cebfc718680dd916047b29fddc076b8a27496c573e976abf
|
||||
public void sendMsg(String mobile, String content) {
|
||||
|
||||
long timestamp = System.currentTimeMillis();
|
||||
String sign = null;
|
||||
try {
|
||||
byte[] signData = ShaUtil.hmacSha256(timestamp + "\n" + secret, secret);
|
||||
sign = URLEncoder.encode(new String(Base64.encodeBase64(signData)), "UTF-8");
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
String sendUrl = String.format("https://oapi.dingtalk.com/robot/send?access_token=%s×tamp=%s&sign=%s", token, timestamp, sign);
|
||||
String msg = String.format("[测试信息] \n\n发往:%s\n\n内容: %s", mobile, content);
|
||||
//log.info("测试信息:{}", msg);
|
||||
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.setContentType(MediaType.APPLICATION_JSON);
|
||||
HttpEntity<DingTalkMsgDTO> request = new HttpEntity<>(new DingTalkMsgDTO(msg), headers);
|
||||
Map resp = restTemplate.postForObject(sendUrl, request, Map.class);
|
||||
System.out.println(resp);
|
||||
}
|
||||
|
||||
@Data
|
||||
private static class DingTalkMsgDTO {
|
||||
|
||||
//消息格式,写死文本
|
||||
private final String msgtype = "markdown";
|
||||
|
||||
private Markdown markdown;
|
||||
|
||||
public DingTalkMsgDTO(String mdText) {
|
||||
markdown = new Markdown();
|
||||
markdown.setTitle("测试短信");
|
||||
markdown.setText(mdText);
|
||||
}
|
||||
|
||||
// private Text text;
|
||||
// public DingTalkMsgDTO(String msg) {
|
||||
// text = new Text();
|
||||
// text.content = msg;
|
||||
// }
|
||||
|
||||
@Data
|
||||
public static class Text {
|
||||
private String content;
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class Markdown {
|
||||
private String title;
|
||||
private String text;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,331 @@
|
|||
package com.alive.server.service;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.alive.server.config.DiscordConfig;
|
||||
import com.alive.server.dto.DiscordlaborUnionDto;
|
||||
import com.alive.server.dto.UserDto;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import okhttp3.*;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.http.HttpEntity;
|
||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.apache.http.impl.client.HttpClientBuilder;
|
||||
import org.apache.http.util.EntityUtils;
|
||||
import org.jooq.DSLContext;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.*;
|
||||
|
||||
import static com.alive.db.jooq.Tables.T_MEMBER;
|
||||
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
public class DiscordService {
|
||||
|
||||
|
||||
@Autowired
|
||||
private DSLContext dslContext;
|
||||
|
||||
/**
|
||||
* 生成授权链接
|
||||
* @return
|
||||
*/
|
||||
public String getAuthorizationUrl(String address) {
|
||||
Map<String,String> map = new HashMap<>();
|
||||
String url = "https://discord.com/oauth2/authorize?";
|
||||
url += "client_id="+ DiscordConfig.CLIENT_ID;
|
||||
//访问权限
|
||||
url += "&response_type=code";
|
||||
//回调地址
|
||||
url += "&redirect_uri="+DiscordConfig.TOKEN_URL;
|
||||
//用户地址
|
||||
url += "&state="+address;
|
||||
url += "&scope=identify+guilds+gdm.join+guilds.join+guilds.members.read";
|
||||
return url;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户token
|
||||
* @param code
|
||||
* @param address
|
||||
*/
|
||||
public String getTokenByCode(String code,String address){
|
||||
try {
|
||||
String clientId = URLEncoder.encode(DiscordConfig.CLIENT_ID, "UTF-8");
|
||||
String clientSecret = URLEncoder.encode(DiscordConfig.CLIENT_SECRET, "UTF-8");
|
||||
String credentials = clientId + ":" + clientSecret;
|
||||
String base64Credentials = Base64.getEncoder().encodeToString(credentials.getBytes());
|
||||
|
||||
OkHttpClient client = new OkHttpClient();
|
||||
String requestBody = null;
|
||||
String refreshToken = DiscordConfig.getRefreshToken(address);
|
||||
String accessToken = DiscordConfig.getAccessToken(address);
|
||||
if(refreshToken != null && accessToken != null){
|
||||
return accessToken;
|
||||
}
|
||||
if(refreshToken == null && accessToken == null && code == null){
|
||||
return null;
|
||||
}
|
||||
if(code != null && StringUtils.isBlank(refreshToken)){
|
||||
String grantType = "authorization_code";
|
||||
// Build request body
|
||||
requestBody = String.format("grant_type="+grantType+"&code=%s&redirect_uri=%s",
|
||||
URLEncoder.encode(code, "UTF-8"),
|
||||
URLEncoder.encode(DiscordConfig.TOKEN_URL, "UTF-8"));
|
||||
}else{
|
||||
String grantType = "refresh_token";
|
||||
//刷新令牌需要的参数
|
||||
requestBody = String.format("grant_type="+grantType+"&refresh_token=%s&redirect_uri=%s",
|
||||
URLEncoder.encode(refreshToken, "UTF-8"),
|
||||
URLEncoder.encode(DiscordConfig.TOKEN_URL, "UTF-8"));
|
||||
}
|
||||
// Build request
|
||||
Request request = new Request.Builder()
|
||||
.url("https://discord.com/api/oauth2/token")
|
||||
.post(RequestBody.create(MediaType.parse("application/x-www-form-urlencoded"), requestBody))
|
||||
.addHeader("Content-Type", "application/x-www-form-urlencoded")
|
||||
.addHeader("Authorization", "Basic " + base64Credentials)
|
||||
.build();
|
||||
|
||||
// Execute request
|
||||
try (Response response = client.newCall(request).execute()) {
|
||||
if (!response.isSuccessful() || response.code() != 200) {
|
||||
throw new IOException("Unexpected response code: " + response);
|
||||
}
|
||||
JSONObject json = JSON.parseObject(response.body().string());
|
||||
accessToken = json.getString("access_token");
|
||||
refreshToken = json.getString("refresh_token");
|
||||
Integer expiresIn = json.getInteger("expires_in");
|
||||
if(StringUtils.isBlank(accessToken) || StringUtils.isBlank(refreshToken)){
|
||||
throw new IOException("failed to obtain the token");
|
||||
}
|
||||
//保存用户访问令牌和刷新令牌
|
||||
DiscordConfig.addAccessToken(address,accessToken,expiresIn);
|
||||
DiscordConfig.addRefreshToken(address,refreshToken,60 * 60 * 60);
|
||||
return accessToken;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
DiscordConfig.deleteAccessToken(address);
|
||||
DiscordConfig.deleteRefreshToken(address);
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 根据code换取token
|
||||
* @param code
|
||||
* @param refreshToken
|
||||
* @param merchantPojo
|
||||
* @return
|
||||
*/
|
||||
/* public DiscordDto getToken(String code,String refreshToken,MerchantPojo merchantPojo) {
|
||||
try {
|
||||
Map<String, Object> formData = new HashMap<>();
|
||||
if(!StringUtils.isBlank(code)){
|
||||
formData.put("grant_type", "authorization_code");
|
||||
formData.put("code", code);
|
||||
}
|
||||
if(!StringUtils.isBlank(refreshToken)){
|
||||
formData.put("refresh_token", refreshToken);
|
||||
formData.put("grant_type", "refresh_token");
|
||||
}
|
||||
//重定向配置的URL,一定要和重定向里面的地址保持一致
|
||||
formData.put("redirect_uri", merchantPojo.getDcRedirectUrl());
|
||||
formData.put("client_id", DiscordConfig.CLIENT_ID);
|
||||
formData.put("client_secret", DiscordConfig.CLIENT_SECRET);
|
||||
// 创建URL对象
|
||||
DiscordDto discordDto = this.doPostForm("https://discord.com/api/oauth2/token",formData);
|
||||
return discordDto;
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}*/
|
||||
|
||||
/**
|
||||
* 获取用户的所有服务器
|
||||
* @param token
|
||||
* @return
|
||||
*/
|
||||
public List<DiscordlaborUnionDto> findLaborUnionList(String token) {
|
||||
try {
|
||||
// 设置请求URL和Bearer Token
|
||||
CloseableHttpClient httpClient = HttpClientBuilder.create().build();
|
||||
HttpGet httpPost = new HttpGet("https://discord.com/api/v9/users/@me/guilds");
|
||||
httpPost.setHeader("Content-Type", "application/json;charset=utf8");
|
||||
httpPost.setHeader("Authorization", "Bearer " + token);
|
||||
CloseableHttpResponse response = null;
|
||||
// 由客户端执行(发送)Post请求
|
||||
response = httpClient.execute(httpPost);
|
||||
// 从响应模型中获取响应实体
|
||||
HttpEntity responseEntity = response.getEntity();
|
||||
if (response.getStatusLine().getStatusCode() == 200 && responseEntity != null) {
|
||||
String responseJson = EntityUtils.toString(responseEntity);
|
||||
JSONArray jsonArray = JSON.parseArray(responseJson);
|
||||
List<DiscordlaborUnionDto> jsonArrayToStringList = JSONObject.parseArray(jsonArray.toJSONString(),DiscordlaborUnionDto.class);
|
||||
return jsonArrayToStringList;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public Boolean findUserLaborUnion(String token, String guildId) {
|
||||
try {
|
||||
// 设置请求URL和Bearer Token
|
||||
CloseableHttpClient httpClient = HttpClientBuilder.create().build();
|
||||
HttpGet httpPost = new HttpGet("https://discord.com/api/v9/users/@me/guilds/" + guildId+"/member");
|
||||
httpPost.setHeader("Content-Type", "application/json;charset=utf8");
|
||||
httpPost.setHeader("Authorization", "Bearer " + token);
|
||||
CloseableHttpResponse response = null;
|
||||
// 由客户端执行(发送)Post请求
|
||||
response = httpClient.execute(httpPost);
|
||||
// 从响应模型中获取响应实体
|
||||
HttpEntity responseEntity = response.getEntity();
|
||||
if (response.getStatusLine().getStatusCode() == 200 && responseEntity != null) {
|
||||
String responseJson = EntityUtils.toString(responseEntity);
|
||||
JSONObject jsonArray = JSON.parseObject(responseJson);
|
||||
if(jsonArray.get("user") != null){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询用户信息
|
||||
* @param address
|
||||
* @return
|
||||
*/
|
||||
public UserDto findUser(String address) {
|
||||
try {
|
||||
String token = this.getTokenByCode(null,address);
|
||||
if(token == null){
|
||||
return null;
|
||||
}
|
||||
// 设置请求URL和Bearer Token
|
||||
CloseableHttpClient httpClient = HttpClientBuilder.create().build();
|
||||
HttpGet httpPost = new HttpGet("https://discord.com/api/v9/users/@me");
|
||||
httpPost.setHeader("Content-Type", "application/json;charset=utf8");
|
||||
httpPost.setHeader("Authorization", "Bearer " + token);
|
||||
CloseableHttpResponse response = null;
|
||||
// 由客户端执行(发送)Post请求
|
||||
response = httpClient.execute(httpPost);
|
||||
// 从响应模型中获取响应实体
|
||||
HttpEntity responseEntity = response.getEntity();
|
||||
if (response.getStatusLine().getStatusCode() == 200 && responseEntity != null) {
|
||||
String responseJson = EntityUtils.toString(responseEntity);
|
||||
JSONObject jsonArray = JSON.parseObject(responseJson);
|
||||
UserDto userDto = JSON.toJavaObject(jsonArray, UserDto.class);
|
||||
return userDto;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询用户是否加入Discord
|
||||
* @param address
|
||||
* @return
|
||||
*/
|
||||
public Boolean joinConfirmation(String address,String guildId) {
|
||||
//刷新用户token
|
||||
String accessToken = this.getTokenByCode(null,address);
|
||||
if(accessToken == null){
|
||||
return false;
|
||||
}
|
||||
//查询用户工会
|
||||
return this.findUserLaborUnion(accessToken,guildId);
|
||||
}
|
||||
|
||||
public void bindUser(String id) {
|
||||
Integer num = dslContext.selectCount().from(T_MEMBER).where(T_MEMBER.DISCORD_ID.eq(id)).fetchAnyInto(Integer.class);
|
||||
Assert.isTrue(num == 0,"The account has been linked Discord");
|
||||
}
|
||||
|
||||
/*public String getDiscordByCodeUrl(DcAttentionReq dcAttentionReq) {
|
||||
String token = this.getRefreshToken(dcAttentionReq.getAddress());
|
||||
String discordUserIdKey = "discord_user_token"+dcAttentionReq.getAddress();
|
||||
//查询用户个人信息
|
||||
String discordUserId = RedisUtil.get(discordUserIdKey);
|
||||
if(discordUserId == null){
|
||||
discordUserId = this.findUser(token).getId();
|
||||
RedisUtil.setEx(discordUserIdKey,discordUserId,60 * 100);
|
||||
}
|
||||
try {
|
||||
//先把原订单取消掉
|
||||
dslContext.update(TASK_LOG).set(TASK_LOG.TASK_TYPE,4).where(TASK_LOG.ADDRESS.eq(dcAttentionReq.getAddress())
|
||||
.and(TASK_LOG.STATUS.eq(3)).and(TASK_LOG.TASK_TYPE.eq(2))).execute();
|
||||
TaskLogRecord log = dslContext.newRecord(TASK_LOG);
|
||||
log.setAddress(dcAttentionReq.getAddress());
|
||||
log.setMerchantId(1);
|
||||
log.setTaskOn("001");
|
||||
log.setType(dcAttentionReq.getCodeNo());
|
||||
log.setStatus(3);
|
||||
log.setUserId(discordUserId);
|
||||
log.setTaskType(2);
|
||||
log.store();
|
||||
|
||||
return DiscordConfig.INVITE_URL;
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}*/
|
||||
|
||||
|
||||
|
||||
|
||||
/* public TgUserReq findChannelMember(DcAttentionReq dcAttentionReq) {
|
||||
TgUserReq tgUserReq = new TgUserReq();
|
||||
tgUserReq.setStatus(0);
|
||||
Assert.isTrue(!StringUtils.isBlank(dcAttentionReq.getAddress()) &&
|
||||
!StringUtils.isBlank(dcAttentionReq.getMerchantOn()) && dcAttentionReq.getCodeNo() != null, "parameter not null");
|
||||
dcAttentionReq.setAddress(dcAttentionReq.getAddress().toLowerCase());
|
||||
if(dcAttentionReq.getDay() != null && dcAttentionReq.getDay() == 1){
|
||||
String value = RedisUtil.get("roost_gpask_discord"+dcAttentionReq.getAddress());
|
||||
if(value != null){
|
||||
tgUserReq.setStatus(1);
|
||||
}
|
||||
}else{
|
||||
TaskLogRecord taskLogRecord = merchantService.getTaskLog(dcAttentionReq.getAddress(),dcAttentionReq.getCodeNo(),3,3);
|
||||
Assert.notNull(taskLogRecord,"tsak is null");
|
||||
tgUserReq.setStatus(taskLogRecord.getTaskType().equals(3) ? 1 : 0);
|
||||
}
|
||||
return tgUserReq;
|
||||
}
|
||||
|
||||
public String getStartTgUrl(DcFaucetReq dcFaucetReq) {
|
||||
MerchantPojo merchantPojo = merchantService.getMerchant(dcFaucetReq.getCodeNo(),dcFaucetReq.getMerchantOn());
|
||||
MerchantConfigPojo merchantConfigPojo = merchantService.getMerchantConfig(merchantPojo.getId());
|
||||
dslContext.update(TASK_LOG).set(TASK_LOG.TASK_TYPE,4).where(TASK_LOG.ADDRESS.eq(dcFaucetReq.getAddress())
|
||||
.and(TASK_LOG.STATUS.eq(3)).and(TASK_LOG.TASK_TYPE.in(1,2)).and(TASK_LOG.MERCHANT_ID.eq(merchantPojo.getId()))).execute();
|
||||
TaskLogRecord log = dslContext.newRecord(TASK_LOG);
|
||||
log.setMerchantId(merchantPojo.getId());
|
||||
log.setAddress(dcFaucetReq.getAddress());
|
||||
log.setTaskOn("00X");
|
||||
log.setType(dcFaucetReq.getCodeNo());
|
||||
log.setTaskType(1);
|
||||
log.setStatus(3);
|
||||
log.setUserId("0");
|
||||
log.store();
|
||||
return merchantConfigPojo.getDcInviteUrl();
|
||||
}*/
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,86 @@
|
|||
package com.alive.server.service;
|
||||
|
||||
import com.alive.commons.config.BaseComponent;
|
||||
import com.alive.commons.util.Md5Util;
|
||||
import com.alive.commons.util.RequestUtil;
|
||||
import com.alive.db.entity.Vo.InvitationCodeVo;
|
||||
import com.alive.db.jooq.tables.records.TMemberRecord;
|
||||
import com.alive.server.dto.TwitterUserDto;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang.math.NumberUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import static com.alive.db.jooq.Tables.T_MEMBER;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
public class MemberService extends BaseComponent {
|
||||
|
||||
public List<Integer> splitAllPid(String allPid) {
|
||||
if (allPid == null || allPid.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
String[] arr = allPid.split(",");
|
||||
List<Integer> res = new ArrayList<>(arr.length);
|
||||
for (String str : arr) {
|
||||
if (NumberUtils.isNumber(str)) {
|
||||
res.add(Integer.parseInt(str));
|
||||
}
|
||||
}
|
||||
Collections.reverse(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
public Integer countTwitterUser(String address) {
|
||||
return dslContext.selectCount().from(T_MEMBER).where(T_MEMBER.ACCOUNT.eq(address).and(T_MEMBER.TWITTER_ID.isNotNull())).fetchAnyInto(Integer.class);
|
||||
}
|
||||
|
||||
public Integer countDiscordUser(String address) {
|
||||
return dslContext.selectCount().from(T_MEMBER).where(T_MEMBER.ACCOUNT.eq(address).and(T_MEMBER.DISCORD_ID.isNotNull())).fetchAnyInto(Integer.class);
|
||||
}
|
||||
|
||||
public void renewalUserDiscord(String address,String discordId) {
|
||||
dslContext.update(T_MEMBER).set(T_MEMBER.DISCORD_ID,discordId).where(T_MEMBER.ACCOUNT.eq(address)).execute();
|
||||
}
|
||||
|
||||
public void renewalUserTwitter(TwitterUserDto dto, String address) {
|
||||
dslContext.update(T_MEMBER).set(T_MEMBER.TWITTER_TYPE,1).set(T_MEMBER.TWITTER_USER_NAME,dto.getUsername()).set(T_MEMBER.TWITTER_ID,dto.getId())
|
||||
.set(T_MEMBER.TWITTER_NAME,dto.getName()).set(T_MEMBER.TWITTER_IMG,dto.getImg()).where(T_MEMBER.ACCOUNT.eq(address)).execute();
|
||||
}
|
||||
|
||||
public TMemberRecord fetchOne(int memberId) {
|
||||
return dslContext.fetchOne(T_MEMBER, T_MEMBER.ID.eq(memberId));
|
||||
}
|
||||
|
||||
public List<TMemberRecord> findTMemberRecordList(int memberId) {
|
||||
return dslContext.select().from(T_MEMBER).where(T_MEMBER.ALL_PID.like(","+memberId+",")).fetchInto(TMemberRecord.class);
|
||||
}
|
||||
|
||||
public Integer findTMemberRecordCount(int memberId) {
|
||||
return dslContext.selectCount().from(T_MEMBER).where(T_MEMBER.ALL_PID.likeRegex(","+memberId+",")).fetchAnyInto(Integer.class);
|
||||
}
|
||||
|
||||
public TMemberRecord fetchOneByUid(String uid) {
|
||||
return dslContext.selectFrom(T_MEMBER).where(T_MEMBER.UID.eq(uid)).fetchAny();
|
||||
}
|
||||
|
||||
public void checkPassword(int memberId, String password) {
|
||||
TMemberRecord memberRecord = dslContext.fetchOne(T_MEMBER, T_MEMBER.ID.eq(memberId));
|
||||
Assert.notNull(memberRecord, "account does not exist");
|
||||
Assert.isTrue(Md5Util.encryptPassword(password).equals(memberRecord.getPasswordLogin()), "wrong password");
|
||||
}
|
||||
/* public void checkPayPassword(int memberId, String password) {
|
||||
TMemberRecord memberRecord = dslContext.fetchOne(T_MEMBER, T_MEMBER.ID.eq(memberId));
|
||||
Assert.notNull(memberRecord, "账号不存在");
|
||||
Assert.isTrue(Md5Util.encryptPassword(password).equals(memberRecord.getPasswordPay()), "支付密码错误");
|
||||
}*/
|
||||
|
||||
public InvitationCodeVo invitationCode() {
|
||||
int memberId = Integer.parseInt(RequestUtil.getCurrentAccount());
|
||||
TMemberRecord memberRecord = dslContext.fetchOne(T_MEMBER, T_MEMBER.ID.eq(memberId));
|
||||
return memberRecord != null ? new InvitationCodeVo().setInvitationCode(memberRecord.getShareCode()) : new InvitationCodeVo();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
package com.alive.server.service;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.telegram.telegrambots.bots.TelegramWebhookBot;
|
||||
import org.telegram.telegrambots.meta.api.methods.BotApiMethod;
|
||||
import org.telegram.telegrambots.meta.api.objects.Update;
|
||||
import org.telegram.telegrambots.meta.api.objects.User;
|
||||
import org.telegram.telegrambots.meta.TelegramBotsApi;
|
||||
import org.telegram.telegrambots.meta.exceptions.TelegramApiRequestException;
|
||||
import org.telegram.telegrambots.meta.api.objects.Chat;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
public class MyTelegramBot extends TelegramWebhookBot {
|
||||
|
||||
private String token ="6811525345:AAFMiaC3Q_h2kn2uXQG7m2YuaIOT9vWG0G0";
|
||||
private String username ="ROOS_Test_Bot";
|
||||
|
||||
@Override
|
||||
public BotApiMethod onWebhookUpdateReceived(Update update) {
|
||||
// 处理 ChatMemberUpdated 事件
|
||||
/*if (update.hasMessage() && update.getMessage().getChatMemberUpdated() != null) {
|
||||
ChatMemberUpdated chatMemberUpdated = update.getMessage().getChatMemberUpdated();
|
||||
processChatMemberUpdated(chatMemberUpdated);
|
||||
}*/
|
||||
System.out.printf("111223");
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public String getBotUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getBotToken() {
|
||||
return token;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getBotPath() {
|
||||
return "http://gqydas.natappfree.cc/telegram/test";
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,112 @@
|
|||
package com.alive.server.service;
|
||||
|
||||
import com.alive.commons.util.RequestUtil;
|
||||
import com.alive.db.entity.NodeBuyLog;
|
||||
import com.alive.db.entity.Vo.WordNodeVo;
|
||||
import com.alive.db.mapper.NodeBuyLogMapper;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 节点认购记录Service业务层处理
|
||||
*
|
||||
* @author HayDen
|
||||
* @date 2024-01-09
|
||||
*/
|
||||
@Service
|
||||
public class NodeBuyLogService
|
||||
{
|
||||
@Autowired
|
||||
private NodeBuyLogMapper nodeSubscribeMapper;
|
||||
|
||||
/**
|
||||
* 查询节点认购记录
|
||||
*
|
||||
* @param id 节点认购记录ID
|
||||
* @return 节点认购记录
|
||||
*/
|
||||
public NodeBuyLog selectNodeSubscribeById(Integer id)
|
||||
{
|
||||
return nodeSubscribeMapper.selectNodeSubscribeById(id);
|
||||
}
|
||||
|
||||
public Integer countBuyLogByUserId(NodeBuyLog nodeSubscribe)
|
||||
{
|
||||
return nodeSubscribeMapper.countBuyLogByUserId(nodeSubscribe);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询节点认购记录列表
|
||||
*
|
||||
* @param nodeSubscribe 节点认购记录
|
||||
* @return 节点认购记录
|
||||
*/
|
||||
public List<NodeBuyLog> selectNodeSubscribeList(NodeBuyLog nodeSubscribe)
|
||||
{
|
||||
List<NodeBuyLog> nodeSubscribeList = nodeSubscribeMapper.selectNodeSubscribeList(nodeSubscribe);
|
||||
return nodeSubscribeList;
|
||||
}
|
||||
|
||||
public NodeBuyLog findNodeSubscribeByOrderNumber(String orderNumber)
|
||||
{
|
||||
return nodeSubscribeMapper.findNodeSubscribeByOrderNumber(orderNumber);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询节点认购记录对象
|
||||
*
|
||||
* @param nodeSubscribe 节点认购记录
|
||||
* @return 节点认购记录
|
||||
*/
|
||||
public NodeBuyLog findNodeSubscribe(NodeBuyLog nodeSubscribe)
|
||||
{
|
||||
nodeSubscribe = nodeSubscribeMapper.findNodeSubscribe(nodeSubscribe);
|
||||
return nodeSubscribe;
|
||||
}
|
||||
|
||||
public WordNodeVo findWordNodeVo()
|
||||
{
|
||||
int memberId = Integer.parseInt(RequestUtil.getCurrentAccount());
|
||||
WordNodeVo wordNodeVo= nodeSubscribeMapper.findWordNodeVo(memberId);
|
||||
if(wordNodeVo == null || StringUtils.isBlank(wordNodeVo.getNodeName())){
|
||||
wordNodeVo = new WordNodeVo();
|
||||
Integer count = this.countBuyLogByUserId(new NodeBuyLog().setUserId(memberId).setStatus(2));
|
||||
if(count != null && count > 0){
|
||||
wordNodeVo.setStatus(2);
|
||||
}else{
|
||||
wordNodeVo.setStatus(3);
|
||||
}
|
||||
}else{
|
||||
wordNodeVo.setStatus(1);
|
||||
}
|
||||
return wordNodeVo;
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改或者添加节点认购记录
|
||||
*
|
||||
* @param nodeSubscribe 节点认购记录
|
||||
* @return 结果
|
||||
*/
|
||||
public int updateOrAddNodeSubscribe(NodeBuyLog nodeSubscribe) {
|
||||
if (nodeSubscribe.getId() != null){
|
||||
return nodeSubscribeMapper.updateNodeSubscribe(nodeSubscribe);
|
||||
}else{
|
||||
return nodeSubscribeMapper.insertNodeSubscribe(nodeSubscribe);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除节点认购记录对象
|
||||
*
|
||||
* @param ids 需要删除的数据ID
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteNodeSubscribeByIds(String ids)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,172 @@
|
|||
package com.alive.server.service;
|
||||
|
||||
import com.alive.commons.enums.WalletLogTypeEnum;
|
||||
import com.alive.commons.util.CoinUtil;
|
||||
import com.alive.db.entity.NodeBuyLog;
|
||||
import com.alive.db.entity.NodeNftConfig;
|
||||
import com.alive.db.jooq.tables.records.TMemberRecord;
|
||||
import com.alive.db.jooq.tables.records.TMemberWalletRecord;
|
||||
import com.alive.db.mapper.NodeNftConfigMapper;
|
||||
import com.alive.server.dto.WalletOperation;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* NFT碎片配置Service业务层处理
|
||||
*
|
||||
* @author HayDen
|
||||
* @date 2024-01-09
|
||||
*/
|
||||
@Service
|
||||
public class NodeNftConfigService
|
||||
{
|
||||
@Autowired
|
||||
private NodeNftConfigMapper nodeNftConfigMapper;
|
||||
|
||||
@Autowired
|
||||
private WalletService walletService;
|
||||
|
||||
@Autowired
|
||||
private MemberService memberService;
|
||||
|
||||
/**
|
||||
* 查询NFT碎片配置
|
||||
*
|
||||
* @param id NFT碎片配置ID
|
||||
* @return NFT碎片配置
|
||||
*/
|
||||
public NodeNftConfig selectNodeNftConfigById(Integer id)
|
||||
{
|
||||
return nodeNftConfigMapper.selectNodeNftConfigById(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询NFT碎片配置列表
|
||||
*
|
||||
* @param nodeNftConfig NFT碎片配置
|
||||
* @return NFT碎片配置
|
||||
*/
|
||||
public List<NodeNftConfig> selectNodeNftConfigList(NodeNftConfig nodeNftConfig)
|
||||
{
|
||||
List<NodeNftConfig> nodeNftConfigList = nodeNftConfigMapper.selectNodeNftConfigList(nodeNftConfig);
|
||||
return nodeNftConfigList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询NFT碎片配置对象
|
||||
*
|
||||
* @param nodeNftConfig NFT碎片配置
|
||||
* @return NFT碎片配置
|
||||
*/
|
||||
public NodeNftConfig findNodeNftConfig(NodeNftConfig nodeNftConfig)
|
||||
{
|
||||
nodeNftConfig = nodeNftConfigMapper.findNodeNftConfig(nodeNftConfig);
|
||||
return nodeNftConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改或者添加NFT碎片配置
|
||||
*
|
||||
* @param nodeNftConfig NFT碎片配置
|
||||
* @return 结果
|
||||
*/
|
||||
public int updateOrAddNodeNftConfig(NodeNftConfig nodeNftConfig) {
|
||||
if (nodeNftConfig.getId() != null){
|
||||
return nodeNftConfigMapper.updateNodeNftConfig(nodeNftConfig);
|
||||
}else{
|
||||
return nodeNftConfigMapper.insertNodeNftConfig(nodeNftConfig);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除NFT碎片配置对象
|
||||
*
|
||||
* @param ids 需要删除的数据ID
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteNodeNftConfigByIds(String ids)
|
||||
{
|
||||
return nodeNftConfigMapper.deleteNodeNftConfigByIds(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 注册赠送奖励、NTF碎片以及贡献值
|
||||
*/
|
||||
public void reward(NodeBuyLog nodeSubscribe) {
|
||||
TMemberWalletRecord walletRecord= null;
|
||||
WalletOperation walletOperation = null;
|
||||
//先给用户自己发放奖励
|
||||
{
|
||||
if(nodeSubscribe.getRbitAmount().compareTo(BigDecimal.ZERO) > 0){
|
||||
//购买盒子获取Rbit奖励数量
|
||||
walletRecord= walletService.getWallet(nodeSubscribe.getUserId(), CoinUtil.getCoinMap().get("RBIT"));
|
||||
walletOperation = WalletOperation.buildParam(1,walletRecord.getId(), WalletLogTypeEnum.RBIT_IS_COMPLIMENTARY_ON_ORDERS,nodeSubscribe.getRbitAmount(),"购买盒子赠送");
|
||||
walletService.operateBalance(walletOperation);
|
||||
}
|
||||
if(nodeSubscribe.getNftAmount().compareTo(BigDecimal.ZERO) > 0){
|
||||
walletRecord= walletService.getWallet(nodeSubscribe.getUserId(), CoinUtil.getCoinMap().get("NFTCHIP"));
|
||||
walletOperation = WalletOperation.buildParam(1,walletRecord.getId(), WalletLogTypeEnum.ORDER_FREE_NFT,nodeSubscribe.getNftAmount(),"购买盒子赠送");
|
||||
walletService.operateBalance(walletOperation);
|
||||
}
|
||||
}
|
||||
|
||||
//查询我的用户信息
|
||||
TMemberRecord tMemberRecord = memberService.fetchOne(nodeSubscribe.getUserId());
|
||||
if(tMemberRecord.getReferId().equals(0)){
|
||||
//用户没有绑定上级,直接返回不计算奖励
|
||||
return;
|
||||
}
|
||||
|
||||
//上级返佣
|
||||
if(nodeSubscribe.getRebate().compareTo(BigDecimal.ZERO) > 0){
|
||||
//返佣金额
|
||||
walletRecord= walletService.getWallet(tMemberRecord.getReferId(), CoinUtil.getCoinMap().get("USDT"));
|
||||
walletOperation = WalletOperation.buildParam(1,walletRecord.getId(), WalletLogTypeEnum.SUBCOMMISSION,nodeSubscribe.getRebate(),"认购下级返佣");
|
||||
walletService.operateBalance(walletOperation);
|
||||
|
||||
//链上支付了,扣回去,但是需要流水统计数据
|
||||
walletOperation = WalletOperation.buildParam(1,walletRecord.getId(), WalletLogTypeEnum.REBATE_TO_ACCOUNT,nodeSubscribe.getRebate().negate(),"返佣到账");
|
||||
walletService.operateBalance(walletOperation);
|
||||
}
|
||||
|
||||
{
|
||||
if(nodeSubscribe.getRbitOne().compareTo(BigDecimal.ZERO) > 0){
|
||||
//1代增加Rbit奖励
|
||||
nodeSubscribe.setRecommendId(tMemberRecord.getReferId());
|
||||
walletRecord= walletService.getWallet(nodeSubscribe.getRecommendId(), CoinUtil.getCoinMap().get("RBIT"));
|
||||
walletOperation = WalletOperation.buildParam(1,walletRecord.getId(), WalletLogTypeEnum.ONE_RBIT_REWARD,nodeSubscribe.getRbitOne(),"1代Rbit奖励");
|
||||
walletService.operateBalance(walletOperation);
|
||||
}
|
||||
if(nodeSubscribe.getNftOne().compareTo(BigDecimal.ZERO) > 0){
|
||||
//1代NFT碎片奖励
|
||||
walletRecord= walletService.getWallet(nodeSubscribe.getRecommendId(), CoinUtil.getCoinMap().get("NFTCHIP"));
|
||||
walletOperation = WalletOperation.buildParam(1,walletRecord.getId(), WalletLogTypeEnum.ONE_NFT_REWARD,nodeSubscribe.getNftOne(),"1代NFT配件奖励");
|
||||
walletService.operateBalance(walletOperation);
|
||||
}
|
||||
}
|
||||
|
||||
tMemberRecord = memberService.fetchOne(tMemberRecord.getReferId());
|
||||
if(tMemberRecord.getReferId().equals(0)){
|
||||
//用户没有2级上级,直接返回不计算奖励
|
||||
return;
|
||||
}
|
||||
{
|
||||
if(nodeSubscribe.getRbitTwo().compareTo(BigDecimal.ZERO) > 0){
|
||||
nodeSubscribe.setIndirectUserId(tMemberRecord.getReferId());
|
||||
walletRecord= walletService.getWallet(nodeSubscribe.getIndirectUserId(), CoinUtil.getCoinMap().get("RBIT"));
|
||||
walletOperation = WalletOperation.buildParam(1,walletRecord.getId(), WalletLogTypeEnum.TWO_RBIT_REWARD,nodeSubscribe.getRbitTwo(),"2代Rbit奖励");
|
||||
walletService.operateBalance(walletOperation);
|
||||
}
|
||||
if(nodeSubscribe.getNftTwo().compareTo(BigDecimal.ZERO) > 0){
|
||||
//2代NFT碎片奖励
|
||||
walletRecord= walletService.getWallet(nodeSubscribe.getIndirectUserId(), CoinUtil.getCoinMap().get("NFTCHIP"));
|
||||
walletOperation = WalletOperation.buildParam(1,walletRecord.getId(), WalletLogTypeEnum.TWO_NFT_REWARD,nodeSubscribe.getNftTwo(),"2代NFT配件奖励");
|
||||
walletService.operateBalance(walletOperation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,87 @@
|
|||
package com.alive.server.service;
|
||||
|
||||
import com.alive.db.entity.NodePriceConfig;
|
||||
import com.alive.db.mapper.NodePriceConfigMapper;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 节点价格区间配置Service业务层处理
|
||||
*
|
||||
* @author HayDen
|
||||
* @date 2024-01-09
|
||||
*/
|
||||
@Service
|
||||
public class NodePriceConfigService
|
||||
{
|
||||
@Autowired
|
||||
private NodePriceConfigMapper nodePriceConfigMapper;
|
||||
|
||||
/**
|
||||
* 查询节点价格区间配置
|
||||
*
|
||||
* @param id 节点价格区间配置ID
|
||||
* @return 节点价格区间配置
|
||||
*/
|
||||
public NodePriceConfig selectNodePriceConfigById(Integer id)
|
||||
{
|
||||
return nodePriceConfigMapper.selectNodePriceConfigById(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询节点价格区间配置列表
|
||||
*
|
||||
* @param nodePriceConfig 节点价格区间配置
|
||||
* @return 节点价格区间配置
|
||||
*/
|
||||
public List<NodePriceConfig> selectNodePriceConfigList(NodePriceConfig nodePriceConfig)
|
||||
{
|
||||
List<NodePriceConfig> nodePriceConfigList = nodePriceConfigMapper.selectNodePriceConfigList(nodePriceConfig);
|
||||
return nodePriceConfigList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询节点价格区间配置对象
|
||||
*
|
||||
* @param nodePriceConfig 节点价格区间配置
|
||||
* @return 节点价格区间配置
|
||||
*/
|
||||
public NodePriceConfig findNodePriceConfig(NodePriceConfig nodePriceConfig)
|
||||
{
|
||||
nodePriceConfig = nodePriceConfigMapper.findNodePriceConfig(nodePriceConfig);
|
||||
return nodePriceConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改或者添加节点价格区间配置
|
||||
*
|
||||
* @param nodePriceConfig 节点价格区间配置
|
||||
* @return 结果
|
||||
*/
|
||||
public int updateOrAddNodePriceConfig(NodePriceConfig nodePriceConfig) {
|
||||
if (nodePriceConfig.getId() != null){
|
||||
return nodePriceConfigMapper.updateNodePriceConfig(nodePriceConfig);
|
||||
}else{
|
||||
return nodePriceConfigMapper.insertNodePriceConfig(nodePriceConfig);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除节点价格区间配置对象
|
||||
*
|
||||
* @param ids 需要删除的数据ID
|
||||
* @return 结果
|
||||
*/
|
||||
public int deleteNodePriceConfigByIds(String ids)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
public BigDecimal getConfigPrice(Long nodeSettingId, Integer number)
|
||||
{
|
||||
return nodePriceConfigMapper.getConfigPrice(nodeSettingId,number);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,273 @@
|
|||
package com.alive.server.service;
|
||||
|
||||
import com.alive.commons.util.NumberUtil;
|
||||
import com.alive.commons.util.RequestUtil;
|
||||
import com.alive.server.api.account.PayNodeReq;
|
||||
import com.alive.server.api.account.PayNodeSmsReq;
|
||||
import com.alive.commons.config.BaseComponent;
|
||||
import com.alive.db.entity.NodeBuyLog;
|
||||
import com.alive.db.entity.NodeSetting;
|
||||
import com.alive.db.entity.Vo.InviteVo;
|
||||
import com.alive.db.entity.Vo.UserInviteVo;
|
||||
import com.alive.db.entity.Vo.UserTeamVo;
|
||||
import com.alive.db.entity.Vo.WordNodeVo;
|
||||
import com.alive.db.jooq.tables.pojos.SysConfigPojo;
|
||||
import com.alive.db.jooq.tables.records.NodeAwardSettingRecord;
|
||||
import com.alive.db.mapper.NodeBuyLogMapper;
|
||||
import com.alive.db.mapper.NodeSettingMapper;
|
||||
import com.alive.server.web3.Web3jServer;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.jooq.DSLContext;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
import static com.alive.db.jooq.Tables.*;
|
||||
|
||||
/**
|
||||
* 节点设置Service业务层处理
|
||||
*
|
||||
* @author HayDen
|
||||
* @date 2024-01-09
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class NodeSettingService extends BaseComponent {
|
||||
@Resource
|
||||
private NodeSettingMapper nodeSettingMapper;
|
||||
|
||||
@Resource
|
||||
private NodeBuyLogMapper nodeSubscribeMapper;
|
||||
|
||||
@Autowired
|
||||
private DSLContext dslContext;
|
||||
|
||||
@Resource
|
||||
private MemberService tMemberService;
|
||||
|
||||
@Autowired
|
||||
private Web3jServer web3jServer;
|
||||
|
||||
|
||||
public boolean buyNode() {
|
||||
int memberId = Integer.parseInt(RequestUtil.getCurrentAccount());
|
||||
Integer code = dslContext.selectCount().from(NODE_BUY_LOG).where(NODE_BUY_LOG.USER_ID.eq(memberId).and(NODE_BUY_LOG.STATUS.eq(3))).fetchAnyInto(Integer.class);
|
||||
return code != null && code > 0;
|
||||
}
|
||||
|
||||
public UserInviteVo findUserInviteVo() {
|
||||
int memberId = Integer.parseInt(RequestUtil.getCurrentAccount());
|
||||
UserInviteVo vo = nodeSettingMapper.findUserInviteVo(memberId);
|
||||
return vo;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 下单购买节点
|
||||
*
|
||||
* @param nodeSetting
|
||||
* @param req
|
||||
*/
|
||||
public NodeBuyLog payNode(NodeSetting nodeSetting, PayNodeReq req) {
|
||||
int memberId = Integer.parseInt(RequestUtil.getCurrentAccount());
|
||||
Assert.isTrue(nodeSetting.getStatus().equals(1), "Not available or sold out");
|
||||
Assert.isTrue(nodeSetting.getNodeTotal() > (nodeSetting.getPurchasedCount() + req.getNumber()), "Insufficient nodes");
|
||||
//计算库存
|
||||
int count = nodeSubscribeMapper.sumBuyCount(memberId);
|
||||
Assert.isTrue((count + req.getNumber()) <= nodeSetting.getPurchaseLimit(), "Only one ROOSBOX can be purchased");
|
||||
SysConfigPojo config = dslContext.select().from(SYS_CONFIG).where(SYS_CONFIG.CONFIG_KEY.eq("USDT_COLLECTION_ADDRESS")).fetchAnyInto(SysConfigPojo.class);
|
||||
NodeAwardSettingRecord pojo = dslContext.selectFrom(NODE_AWARD_SETTING).where(NODE_AWARD_SETTING.NODE_SETTING_ID.eq(nodeSetting.getId())).fetchAny();
|
||||
|
||||
UserTeamVo userTeamVo = nodeSubscribeMapper.findUserAddressById(memberId);
|
||||
userTeamVo = userTeamVo == null ? new UserTeamVo() : userTeamVo;
|
||||
NodeBuyLog buyLog1 = new NodeBuyLog();
|
||||
Lock lock = new ReentrantLock();
|
||||
lock.lock();
|
||||
try {
|
||||
//查询奖励配置
|
||||
if (pojo != null) {
|
||||
//上级返佣
|
||||
buyLog1.setRebate(req.getTatolAmount().multiply(pojo.getRebate()));
|
||||
buyLog1.setRbitAmount(new BigDecimal(req.getNumber()).multiply(pojo.getRbitAmount()));
|
||||
buyLog1.setRbitOne(buyLog1.getRbitAmount().multiply(pojo.getRbitOne()));
|
||||
buyLog1.setRbitTwo(buyLog1.getRbitAmount().multiply(pojo.getRebateTwo()));
|
||||
buyLog1.setNftAmount(new BigDecimal(req.getNumber()).multiply(pojo.getNftAmount()));
|
||||
buyLog1.setNftOne(buyLog1.getNftAmount().multiply(pojo.getNftOne()));
|
||||
buyLog1.setNftTwo(buyLog1.getNftAmount().multiply(pojo.getNftTwo()));
|
||||
}
|
||||
buyLog1.setRecommendId(userTeamVo.getId());
|
||||
buyLog1.setBuyCount(req.getNumber());
|
||||
buyLog1.setPayCoin(nodeSetting.getBuyCoinName());
|
||||
buyLog1.setBuyAmount(req.getTatolAmount());
|
||||
buyLog1.setNodeSettingId(nodeSetting.getId());
|
||||
buyLog1.setStatus(1);
|
||||
buyLog1.setWalletAddress(RequestUtil.getAddress());
|
||||
buyLog1.setUserId(memberId);
|
||||
buyLog1.setOrderNumber(NumberUtil.getUUIDBy16());
|
||||
buyLog1.setOutAddress(config.getValue());
|
||||
nodeSubscribeMapper.insertNodeSubscribe(buyLog1);
|
||||
} catch (Exception e) {
|
||||
log.error("下单出现错误,错误码:{}", e);
|
||||
e.getMessage();
|
||||
throw new RuntimeException(e);
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
config = dslContext.select().from(SYS_CONFIG).where(SYS_CONFIG.CONFIG_KEY.eq("USDT_WEI")).fetchAnyInto(SysConfigPojo.class);
|
||||
buyLog1.setBuyAmount(new BigDecimal(config.getValue()).multiply(buyLog1.getBuyAmount()));
|
||||
buyLog1.setRebate(new BigDecimal(config.getValue()).multiply(buyLog1.getRebate()));
|
||||
String address = userTeamVo.getAccount();
|
||||
if (address == null || pojo.getRebate().compareTo(BigDecimal.ZERO) == 0 || !address.substring(0, 2).equals("0x") || address.length() < 30) {
|
||||
buyLog1.setAddress(BigInteger.ZERO.toString());
|
||||
buyLog1.setRebateRatio(new BigInteger("100"));
|
||||
buyLog1.setNum(100);
|
||||
} else {
|
||||
|
||||
BigDecimal rebate = pojo.getRebate().multiply(new BigDecimal(config.getValue()));
|
||||
rebate = rebate.add(new BigDecimal(300));
|
||||
Integer num = getRandom4();
|
||||
rebate = rebate.multiply(new BigDecimal(num));
|
||||
buyLog1.setRebateRatio(new BigInteger(rebate.stripTrailingZeros().toPlainString()));
|
||||
buyLog1.setNum((num * 3) + 500 - num);
|
||||
buyLog1.setAddress(Web3jServer.addressToUint160(address).add(new BigInteger("300")).subtract(new BigInteger(num.toString())).toString());
|
||||
}
|
||||
return buyLog1;
|
||||
}
|
||||
|
||||
public static Integer getRandom4() {
|
||||
Random random = new Random();
|
||||
// 生成0到9之间的随机数(包括0但不包括10)
|
||||
int randomNum = random.nextInt(10);
|
||||
if (randomNum == 0) {
|
||||
return getRandom4();
|
||||
}
|
||||
return randomNum;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 查询用户邀请列表
|
||||
*/
|
||||
public List<InviteVo> findInviteVoList() {
|
||||
int memberId = Integer.parseInt(RequestUtil.getCurrentAccount());
|
||||
List<InviteVo> inviteVos = nodeSubscribeMapper.findInviteVoList(memberId);
|
||||
for (InviteVo vo : inviteVos) {
|
||||
vo.setStatus(vo.getStatus() == null ? 0 : 1);
|
||||
}
|
||||
return inviteVos;
|
||||
}
|
||||
|
||||
|
||||
public Boolean payNodeSms(PayNodeSmsReq req) {
|
||||
NodeBuyLog nodeSubscribe = nodeSubscribeMapper.findNodeSubscribe(new NodeBuyLog().setOrderNumber(req.getOrderNumber()).setStatus(1));
|
||||
Assert.isTrue(nodeSubscribe != null && nodeSubscribe.getStatus().equals(1), "Order error");
|
||||
if (req.getStatus().equals(2)) {
|
||||
nodeSubscribe.setStatus(4);
|
||||
nodeSubscribeMapper.updateNodeSubscribe(nodeSubscribe);
|
||||
return true;
|
||||
}
|
||||
NodeBuyLog log = nodeSubscribeMapper.findNodeSubscribe(new NodeBuyLog().setHash(req.getHash()));
|
||||
Assert.isTrue(log == null, "Repetition hash");
|
||||
nodeSubscribe.setStatus(2);
|
||||
nodeSubscribe.setHash(req.getHash());
|
||||
if (nodeSubscribe.getStatus() == 2) {
|
||||
//加库存
|
||||
// nodeSettingMapper.addInventory(nodeSubscribe.getBuyCount(),nodeSubscribe.getNodeId());
|
||||
}
|
||||
nodeSubscribeMapper.updateNodeSubscribe(nodeSubscribe);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 查询节点设置
|
||||
*
|
||||
* @param id 节点设置ID
|
||||
* @return 节点设置
|
||||
*/
|
||||
public NodeSetting selectNodeSettingById(Integer id) {
|
||||
return nodeSettingMapper.selectNodeSettingById(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询节点设置列表
|
||||
*
|
||||
* @param nodeSetting 节点设置
|
||||
* @return 节点设置
|
||||
*/
|
||||
public List<NodeSetting> selectNodeSettingList(NodeSetting nodeSetting) {
|
||||
List<NodeSetting> nodeSettingList = nodeSettingMapper.selectNodeSettingList(nodeSetting);
|
||||
BigDecimal mul = new BigDecimal("100");
|
||||
for (NodeSetting nodeSetting1 : nodeSettingList) {
|
||||
nodeSetting1.setRebateRatio(nodeSetting1.getRebateRatio().multiply(mul));
|
||||
nodeSetting1.setRbitOne(nodeSetting1.getRbitOne().multiply(mul));
|
||||
nodeSetting1.setNftOne(nodeSetting1.getNftOne().multiply(mul));
|
||||
nodeSetting1.setNftTwo(nodeSetting1.getNftTwo().multiply(mul));
|
||||
nodeSetting1.setRebateTwo(nodeSetting1.getRebateTwo().multiply(mul));
|
||||
}
|
||||
return nodeSettingList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询节点设置对象
|
||||
*
|
||||
* @param nodeSetting 节点设置
|
||||
* @return 节点设置
|
||||
*/
|
||||
public NodeSetting findNodeSetting(NodeSetting nodeSetting) {
|
||||
nodeSetting = nodeSettingMapper.findNodeSetting(nodeSetting);
|
||||
return nodeSetting;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 修改或者添加节点设置
|
||||
*
|
||||
* @param nodeSetting 节点设置
|
||||
* @return 结果
|
||||
*/
|
||||
public int updateOrAddNodeSetting(NodeSetting nodeSetting) {
|
||||
if (nodeSetting.getId() != null) {
|
||||
return nodeSettingMapper.updateNodeSetting(nodeSetting);
|
||||
} else {
|
||||
return nodeSettingMapper.insertNodeSetting(nodeSetting);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public List<WordNodeVo> getWOrdNodePro() {
|
||||
int memberId = Integer.parseInt(RequestUtil.getCurrentAccount());
|
||||
/*web3jServer.getWeb3j().ethGetTransactionReceipt(null);
|
||||
|
||||
// ERC721 合约地址和查询的地址
|
||||
String contractAddress = web3jServer.bftContract;
|
||||
String ownerAddress = "0x1167398aa2b694edb1c24874d4c7d70340e81606";
|
||||
|
||||
// 加载 ERC721 合约 ABI
|
||||
// 替换 YOUR_CONTRACT_ADDRESS 和 YOUR_CONTRACT_ABI
|
||||
String contractAddress = "YOUR_CONTRACT_ADDRESS";
|
||||
String contractABI = "YOUR_CONTRACT_ABI";
|
||||
|
||||
// 创建 ERC721 合约实例
|
||||
ERC721 contract = ERC721.load(contractAddress, web3j, credentials, Contract.GAS_PRICE, Contract.GAS_LIMIT);
|
||||
|
||||
// 获取地址的 NFT 数量
|
||||
String ownerAddress = "ADDRESS_TO_CHECK"; // 替换为您要查询的地址
|
||||
BigInteger nftCount = contract.balanceOf(ownerAddress).send();
|
||||
System.out.println("Address " + ownerAddress + " has " + nftCount + " NFTs.");*/
|
||||
return nodeSettingMapper.getWOrdNodePro(memberId);
|
||||
}
|
||||
|
||||
public String contractAddress() {
|
||||
SysConfigPojo config = dslContext.select().from(SYS_CONFIG).where(SYS_CONFIG.CONFIG_KEY.eq("CONTRACT_ADDRESS")).fetchAnyInto(SysConfigPojo.class);
|
||||
return config.getValue();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
package com.alive.server.service;
|
||||
|
||||
import com.alive.server.dto.TransferDto;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.jooq.DSLContext;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
|
||||
import static com.alive.db.jooq.Tables.ACTIVITY_LOG;
|
||||
import static com.alive.db.jooq.Tables.T_MEMBER;
|
||||
|
||||
/**
|
||||
* 链上转账API
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class OnChainTransfersService {
|
||||
|
||||
|
||||
@Autowired
|
||||
private DSLContext dslContext;
|
||||
|
||||
@Autowired
|
||||
private TokenTransferServer tokenTransferServer;
|
||||
|
||||
/**
|
||||
* 执行链上转账,换回转账HASH
|
||||
* @return
|
||||
*/
|
||||
public void transfer() {
|
||||
List<TransferDto> activityLogRecords = dslContext.select(ACTIVITY_LOG.ID,ACTIVITY_LOG.SUPERIOR_ADDRESS,ACTIVITY_LOG.ADDRESS,ACTIVITY_LOG.AMOUNT,ACTIVITY_LOG.SUPERIOR_AMOUNT,T_MEMBER.REFER_ID)
|
||||
.from(ACTIVITY_LOG).leftJoin(T_MEMBER).on(ACTIVITY_LOG.ADDRESS.eq(T_MEMBER.ACCOUNT))
|
||||
.where(ACTIVITY_LOG.TYPE.eq(2)
|
||||
.and(ACTIVITY_LOG.TRANSFER_TYPE.eq(0))).fetchInto(TransferDto.class);
|
||||
for (TransferDto logRecord : activityLogRecords){
|
||||
//用户转账的地址
|
||||
String address = logRecord.getAddress();
|
||||
BigDecimal amount = logRecord.getAmount();
|
||||
// 将以太币数量转换为 Wei
|
||||
BigDecimal ethInWei = amount.multiply(BigDecimal.TEN.pow(18));
|
||||
//执行用户链上转账
|
||||
String hash = tokenTransferServer.transferTo(ethInWei,address,0);
|
||||
if(hash == null){
|
||||
continue;
|
||||
}
|
||||
//上级转账金额
|
||||
if(logRecord.getSuperiorAddress() != null && logRecord.getSuperiorAmount().compareTo(BigDecimal.ZERO) > 0){
|
||||
// 将以太币数量转换为 Wei
|
||||
ethInWei = logRecord.getSuperiorAmount().multiply(BigDecimal.TEN.pow(18));
|
||||
//执行用户上级链上转账
|
||||
String superiorHash = tokenTransferServer.transferTo(ethInWei,logRecord.getSuperiorAddress(),0);
|
||||
if(superiorHash != null){
|
||||
hash = hash +" | " + superiorHash;
|
||||
}
|
||||
}
|
||||
dslContext.update(ACTIVITY_LOG).set(ACTIVITY_LOG.TRANSFER_TYPE,1).set(ACTIVITY_LOG.HASHS,hash).where(ACTIVITY_LOG.ID.eq(logRecord.getId())).execute();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,167 @@
|
|||
package com.alive.server.service;
|
||||
|
||||
import com.alive.commons.config.BaseComponent;
|
||||
import com.alive.commons.enums.WalletLogTypeEnum;
|
||||
import com.alive.commons.model.BasePageReq;
|
||||
import com.alive.commons.util.CoinUtil;
|
||||
import com.alive.commons.util.RequestUtil;
|
||||
import com.alive.db.entity.Vo.*;
|
||||
import com.alive.db.jooq.tables.records.NodeTaskLogRecord;
|
||||
import com.alive.db.jooq.tables.records.NodeTaskRecord;
|
||||
import com.alive.db.jooq.tables.records.TMemberRecord;
|
||||
import com.alive.db.jooq.tables.records.TMemberWalletRecord;
|
||||
import com.alive.db.mapper.PersonalCenterMapper;
|
||||
import com.alive.server.api.account.TeskReq;
|
||||
import com.alive.server.dto.WalletOperation;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.*;
|
||||
|
||||
import static com.alive.db.jooq.Tables.*;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
public class PersonalCenterService extends BaseComponent {
|
||||
|
||||
@Autowired
|
||||
private PersonalCenterMapper personalCenterMapper;
|
||||
|
||||
@Autowired
|
||||
private MemberService memberService;
|
||||
|
||||
@Autowired
|
||||
private WalletService walletService;
|
||||
|
||||
public List<TeamRewardVo> findTeamRewardVoList(Integer grade) {
|
||||
int memberId = Integer.parseInt(RequestUtil.getCurrentAccount());
|
||||
List<TMemberRecord> tMemberRecords = dslContext.select().from(T_MEMBER).where(T_MEMBER.REFER_ID.eq(memberId)).fetchInto(TMemberRecord.class);
|
||||
if(grade == 2 && tMemberRecords != null && tMemberRecords.size() > 0){
|
||||
List<Integer> userIds = new ArrayList<>();
|
||||
for (TMemberRecord user : tMemberRecords){
|
||||
userIds.add(user.getId());
|
||||
}
|
||||
tMemberRecords = dslContext.select().from(T_MEMBER).where(T_MEMBER.REFER_ID.in(userIds)).fetchInto(TMemberRecord.class);
|
||||
}
|
||||
List<TeamRewardVo> list = personalCenterMapper.findTeamRewardVoList(grade,memberId);
|
||||
List<TeamRewardVo> rewardVos = new ArrayList<>();
|
||||
for (TMemberRecord tMemberRecord : tMemberRecords){
|
||||
TeamRewardVo teamRewardVo = new TeamRewardVo();
|
||||
Integer lent = tMemberRecord.getAccount().length();
|
||||
teamRewardVo.setAddress(tMemberRecord.getAccount().substring(0,5)+"....."+tMemberRecord.getAccount().substring(lent-5,lent));
|
||||
teamRewardVo.setNumber("0");
|
||||
for(TeamRewardVo teamReward : list){
|
||||
if(tMemberRecord.getAccount().equals(teamReward.getAddress())){
|
||||
teamRewardVo.setNumber(new BigDecimal(teamReward.getNumber()).stripTrailingZeros().toPlainString());
|
||||
}
|
||||
}
|
||||
rewardVos.add(teamRewardVo);
|
||||
}
|
||||
return rewardVos;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询个人中心数据
|
||||
*/
|
||||
public RecommendVo referralReward() {
|
||||
int memberId = Integer.parseInt(RequestUtil.getCurrentAccount());
|
||||
RecommendVo recommendVo = personalCenterMapper.referralReward(memberId);
|
||||
recommendVo = recommendVo == null ? new RecommendVo().setRebate("0").setOneBrit("0").setOneNft("0").setTwoBrit("0").setTwoNft("0") : recommendVo;
|
||||
recommendVo.setInvitationCode(memberService.fetchOne(memberId).getShareCode());
|
||||
recommendVo.setRebate(new BigDecimal(recommendVo.getRebate()).intValue()+"%");
|
||||
recommendVo.setOneBrit(new BigDecimal(recommendVo.getOneBrit()).intValue()+"%");
|
||||
recommendVo.setOneNft(new BigDecimal(recommendVo.getOneNft()).intValue()+"%");
|
||||
recommendVo.setTwoBrit(new BigDecimal(recommendVo.getTwoBrit()).intValue()+"%");
|
||||
recommendVo.setTwoNft(new BigDecimal(recommendVo.getTwoNft()).intValue()+"%");
|
||||
//查询推荐奖励
|
||||
RecommendVo recommend = personalCenterMapper.rewardStatisticsByRecommendId(memberId);
|
||||
recommend = recommend == null ? new RecommendVo() : recommend;
|
||||
recommendVo.setOneNftAmount(new BigDecimal(recommend.getOneNftAmount()).stripTrailingZeros().toPlainString());
|
||||
recommendVo.setBitAmount(new BigDecimal(recommend.getBitAmount()).stripTrailingZeros().toPlainString());
|
||||
recommendVo.setUsdtAmount(new BigDecimal(recommend.getUsdtAmount()).stripTrailingZeros().toPlainString());
|
||||
|
||||
RecommendVo indirectUser = personalCenterMapper.rewardStatisticsByIndirectUserId(memberId);
|
||||
String amount = personalCenterMapper.sumRbitAmountById(memberId);
|
||||
indirectUser = indirectUser == null ? new RecommendVo() : indirectUser;
|
||||
recommendVo.setTwoNftAmount(new BigDecimal(indirectUser.getTwoNftAmount()).stripTrailingZeros().toPlainString());
|
||||
recommendVo.setBitAmount((new BigDecimal(indirectUser.getBitAmount()).add(new BigDecimal(recommendVo.getBitAmount()))
|
||||
.add(new BigDecimal(amount))).stripTrailingZeros().toPlainString());
|
||||
return recommendVo;
|
||||
}
|
||||
|
||||
public String minerFittings() {
|
||||
int memberId = Integer.parseInt(RequestUtil.getCurrentAccount());
|
||||
TMemberWalletRecord tMemberWalletRecord = walletService.getWallet(memberId,CoinUtil.getCoinMap().get("NFTCHIP"));
|
||||
return tMemberWalletRecord.getBalance().stripTrailingZeros().toPlainString();
|
||||
}
|
||||
|
||||
public MyIntegralVo myBonusPoints() {
|
||||
int memberId = Integer.parseInt(RequestUtil.getCurrentAccount());
|
||||
MyIntegralVo myIntegralVo = personalCenterMapper.myBonusPoints(memberId, CoinUtil.getCoinMap().get("POINTS"));
|
||||
myIntegralVo.setMyIntegral(new BigDecimal(myIntegralVo.getMyIntegral()).stripTrailingZeros().toPlainString());
|
||||
myIntegralVo.setRecommendationPoints(new BigDecimal(myIntegralVo.getRecommendationPoints()).stripTrailingZeros().toPlainString());
|
||||
myIntegralVo.setIVeFinished(new BigDecimal(myIntegralVo.getIVeFinished()).stripTrailingZeros().toPlainString());
|
||||
myIntegralVo.setRecommend(new BigDecimal(myIntegralVo.getRecommend()).stripTrailingZeros().toPlainString());
|
||||
return myIntegralVo;
|
||||
}
|
||||
|
||||
public List<TaskVo> recommendedCompletionList(BasePageReq basePageReq) {
|
||||
int memberId = Integer.parseInt(RequestUtil.getCurrentAccount());
|
||||
List<TaskVo> taskVos = personalCenterMapper.recommendedCompletionList(memberId,basePageReq.getOffset(),basePageReq.getSize());
|
||||
for (TaskVo task : taskVos){
|
||||
Integer lent = task.getAddress().length();
|
||||
task.setAddress(task.getAddress().substring(0,5)+"....."+task.getAddress().substring(lent-5,lent));
|
||||
task.setNumber(new BigDecimal(task.getNumber()).stripTrailingZeros().toPlainString());
|
||||
}
|
||||
return taskVos;
|
||||
}
|
||||
|
||||
public List<NodeTaskVo> nodeTask() {
|
||||
int memberId = Integer.parseInt(RequestUtil.getCurrentAccount());
|
||||
List<NodeTaskVo> taskVos = new ArrayList<>();
|
||||
List<NodeTaskRecord> nodeTaskRecords = dslContext.select().from(NODE_TASK).where().fetchInto(NodeTaskRecord.class);
|
||||
List<NodeTaskLogRecord> logs = dslContext.select().from(NODE_TASK_LOG).where(NODE_TASK_LOG.MEMBER_ID.eq(memberId).and(NODE_TASK_LOG.STATE.in(1,2))).fetchInto(NodeTaskLogRecord.class);
|
||||
for (NodeTaskRecord nodeTaskRecord : nodeTaskRecords){
|
||||
NodeTaskVo nodeTaskVo = new NodeTaskVo();
|
||||
nodeTaskVo.setNumber(nodeTaskRecord.getAwardValue().stripTrailingZeros().toPlainString());
|
||||
nodeTaskVo.setType(nodeTaskRecord.getType());
|
||||
nodeTaskVo.setState(0);
|
||||
nodeTaskVo.setCoinName(CoinUtil.getCoinName(nodeTaskRecord.getCoinId()));
|
||||
for (NodeTaskLogRecord log : logs){
|
||||
if(nodeTaskRecord.getId().equals(log.getTaskId())){
|
||||
nodeTaskVo.setState(log.getState());
|
||||
nodeTaskVo.setId(log.getId());
|
||||
nodeTaskVo.setCoinName(log.getCoinName());
|
||||
}
|
||||
}
|
||||
taskVos.add(nodeTaskVo);
|
||||
}
|
||||
return taskVos;
|
||||
}
|
||||
|
||||
public Map<String, Boolean> taskReward(TeskReq req) {
|
||||
int memberId = Integer.parseInt(RequestUtil.getCurrentAccount());
|
||||
TMemberRecord tMemberRecord = memberService.fetchOne(memberId);
|
||||
NodeTaskLogRecord logs = dslContext.select().from(NODE_TASK_LOG).where(NODE_TASK_LOG.MEMBER_ID.eq(memberId).and(NODE_TASK_LOG.ID.eq(req.getId()))).fetchAnyInto(NodeTaskLogRecord.class);
|
||||
Assert.isTrue(logs != null && logs.getMemberId().equals(memberId), "Order does not exist");
|
||||
Assert.isTrue(logs.getState().equals(1), "Unable to claim rewards");
|
||||
logs.setState(2);
|
||||
logs.store();
|
||||
|
||||
//购买盒子获取Rbit奖励数量
|
||||
TMemberWalletRecord walletRecord= walletService.getWallet(memberId, CoinUtil.getCoinMap().get(logs.getCoinName()));
|
||||
WalletOperation walletOperation = WalletOperation.buildParam(1,walletRecord.getId(), WalletLogTypeEnum.TASK_REWARD,logs.getAwardValue(),"领取任务奖励");
|
||||
walletService.operateBalance(walletOperation);
|
||||
|
||||
//给推荐人奖励
|
||||
if(logs.getRecommendValue().compareTo(BigDecimal.ZERO) != 0 && tMemberRecord.getReferId() > 0){
|
||||
walletRecord= walletService.getWallet(tMemberRecord.getReferId(), CoinUtil.getCoinMap().get(logs.getCoinName()));
|
||||
walletOperation = WalletOperation.buildParam(1,walletRecord.getId(), WalletLogTypeEnum.RECOMMENDER_ASSIGNMENT_REWARD,logs.getAwardValue(),"推荐人任务奖励");
|
||||
walletService.operateBalance(walletOperation);
|
||||
}
|
||||
return (Map<String, Boolean>) new TreeMap<>().put("result",true);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,93 @@
|
|||
package com.alive.server.service;
|
||||
|
||||
import com.alive.commons.util.JsonUtil;
|
||||
import com.alive.commons.util.RedisUtil;
|
||||
import com.alive.db.jooq.tables.pojos.SysConfigPojo;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.jooq.DSLContext;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
import static com.alive.db.jooq.Tables.SYS_CONFIG;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
public class SysConfigService {
|
||||
|
||||
@Autowired
|
||||
private DSLContext dslContext;
|
||||
|
||||
public BigDecimal getNumValue(String key, BigDecimal _default) {
|
||||
BigDecimal result = getNumValue(key);
|
||||
return result != null ? result : _default;
|
||||
}
|
||||
|
||||
//获取数字
|
||||
public BigDecimal getNumValue(String key) {
|
||||
SysConfigPojo entity = getEntityWithCache(key);
|
||||
if (entity == null || entity.getValue() == null || entity.getValue().isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
return new BigDecimal(entity.getValue());
|
||||
}
|
||||
|
||||
//获取百分数,未乘100,1% -> 0.01
|
||||
public BigDecimal getPercentValue(String key) {
|
||||
SysConfigPojo entity = getEntityWithCache(key);
|
||||
if (entity == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new BigDecimal(entity.getValue());
|
||||
}
|
||||
|
||||
//获取字符串配置
|
||||
public String getStringValue(String key) {
|
||||
SysConfigPojo entity = getEntityWithCache(key);
|
||||
if (entity == null) {
|
||||
return null;
|
||||
}
|
||||
return entity.getValue();
|
||||
}
|
||||
|
||||
//获取json配置,获取后需要强转
|
||||
public Object getObjectValue(String key, Class<?> targetClass) {
|
||||
SysConfigPojo entity = getEntityWithCache(key);
|
||||
if (entity == null) {
|
||||
return null;
|
||||
}
|
||||
return JsonUtil.fromJson(entity.getValue(), targetClass);
|
||||
}
|
||||
|
||||
public Integer getIntValue(String key) {
|
||||
SysConfigPojo entity = getEntityWithCache(key);
|
||||
if (entity == null) {
|
||||
return null;
|
||||
}
|
||||
return Integer.parseInt(entity.getValue());
|
||||
}
|
||||
|
||||
private SysConfigPojo getEntityWithCache(String key) {
|
||||
String cacheKey = "ids:sysConfig:" + key;
|
||||
String cacheValue = RedisUtil.get(cacheKey);
|
||||
if (cacheValue != null) {
|
||||
return JsonUtil.fromJson(cacheValue, SysConfigPojo.class);
|
||||
}
|
||||
SysConfigPojo entity = dslContext.selectFrom(SYS_CONFIG)
|
||||
.where(SYS_CONFIG.CONFIG_KEY.eq(key))
|
||||
.fetchAnyInto(SysConfigPojo.class);
|
||||
|
||||
RedisUtil.setEx(cacheKey, JsonUtil.toJson(entity), 5);
|
||||
return entity;
|
||||
}
|
||||
|
||||
public void update(String key, String value) {
|
||||
dslContext.update(SYS_CONFIG)
|
||||
.set(SYS_CONFIG.VALUE, value)
|
||||
.where(SYS_CONFIG.CONFIG_KEY.eq(key))
|
||||
.execute();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,291 @@
|
|||
package com.alive.server.service;
|
||||
|
||||
|
||||
import com.alive.server.dto.*;
|
||||
import com.alive.commons.util.DateUtils;
|
||||
import com.alive.db.jooq.tables.records.ActivityLogRecord;
|
||||
import com.alive.server.config.DiscordConfig;
|
||||
import com.alive.server.config.TwitterConfig;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.jooq.DSLContext;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.sql.Timestamp;
|
||||
import java.util.*;
|
||||
|
||||
import static com.alive.db.jooq.Tables.*;
|
||||
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
public class TaskService {
|
||||
|
||||
@Autowired
|
||||
private DSLContext dslContext;
|
||||
|
||||
@Autowired
|
||||
private TwitterService twitterService;
|
||||
|
||||
@Autowired
|
||||
private DiscordService discordService;
|
||||
|
||||
@Autowired
|
||||
private TelegramServer telegramServer;
|
||||
|
||||
/**
|
||||
* 检测用户是否完成任务 关注、改名
|
||||
*/
|
||||
public void optimismExec() {
|
||||
List<ActivityLogRecord> activityLogRecords = dslContext.selectFrom(ACTIVITY_LOG).where(ACTIVITY_LOG.TYPE.eq(1)
|
||||
.and(ACTIVITY_LOG.CONFIG_TYPE.in(1,5))).fetch();
|
||||
if(activityLogRecords == null || activityLogRecords.size() <= 0){
|
||||
return;
|
||||
}
|
||||
for (ActivityLogRecord log : activityLogRecords){
|
||||
if(log.getConfigType().equals(1)){
|
||||
//执行检查关注操作
|
||||
String accessToken = TwitterConfig.getAccessToken(log.getAddress());
|
||||
//重新刷新token
|
||||
if(accessToken == null && twitterService.requestBearerToken(log.getAddress(),null) == null){
|
||||
continue;
|
||||
}
|
||||
accessToken = TwitterConfig.getAccessToken(log.getAddress());
|
||||
//查询用户自己的账号
|
||||
TwitterUserDto twitterUserDto = twitterService.getUserInfoByToken(accessToken);
|
||||
//执行关注
|
||||
AttentionDto attentionDto = twitterService.attention(accessToken,twitterUserDto.getId(),TwitterConfig.DEVELOPERS);
|
||||
if(attentionDto != null && attentionDto.getFollowing()){
|
||||
log.setType(2);
|
||||
}else{
|
||||
log.setType(3);
|
||||
}
|
||||
}else{
|
||||
String accessToken = TwitterConfig.getAccessToken(log.getAddress());
|
||||
//重新刷新token
|
||||
if(accessToken == null && twitterService.requestBearerToken(log.getAddress(),null) == null){
|
||||
continue;
|
||||
}
|
||||
accessToken = TwitterConfig.getAccessToken(log.getAddress());
|
||||
TwitterUserDto twitterUserDto = twitterService.getUserInfoByToken(accessToken);
|
||||
//需要修改推特的后缀名
|
||||
String name = log.getMark();
|
||||
String twitterName = twitterUserDto.getName().substring(twitterUserDto.getName().length() - name.length(),twitterUserDto.getName().length());
|
||||
if(name.toLowerCase().equals(twitterName.toLowerCase())){
|
||||
//任务完成
|
||||
log.setType(2);
|
||||
//更新用户推特信息
|
||||
dslContext.update(T_MEMBER).set(T_MEMBER.TWITTER_IMG,twitterUserDto.getImg()).set(T_MEMBER.TWITTER_NAME,twitterUserDto.getName())
|
||||
.set(T_MEMBER.TWITTER_USER_NAME,twitterUserDto.getUsername()).set(T_MEMBER.TWITTER_ID,twitterUserDto.getId())
|
||||
.where(T_MEMBER.ACCOUNT.eq(log.getAddress())).execute();
|
||||
|
||||
}
|
||||
}
|
||||
if(log.getType().equals(1) && DateUtils.addMinute(log.getCreateTime(),120).getTime() < System.currentTimeMillis()){
|
||||
//任务创建超过2小时,任务失败
|
||||
log.setType(3);
|
||||
}
|
||||
//更新数据
|
||||
if(log.getType().equals(2) || log.getType().equals(3)){
|
||||
log.store();
|
||||
}
|
||||
if(log.getType().equals(2)){
|
||||
//增加用户资产统计
|
||||
dslContext.update(ACTIVITY_STATISTICS).set(ACTIVITY_STATISTICS.AMOUNT,ACTIVITY_STATISTICS.AMOUNT.add(log.getAmount())).where(ACTIVITY_STATISTICS.ADDRESS.eq(log.getAddress())).execute();
|
||||
dslContext.update(ACTIVITY_STATISTICS).set(ACTIVITY_STATISTICS.AMOUNT,ACTIVITY_STATISTICS.AMOUNT.add(log.getSuperiorAmount())).where(ACTIVITY_STATISTICS.ADDRESS.eq(log.getSuperiorAddress())).execute();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检测用户是否完成任务 转载、点赞
|
||||
*/
|
||||
public void activeExec() {
|
||||
List<TwitterTransshipmentDto> activityLogRecords = dslContext.select(ACTIVITY_LOG.ID.as("id"),
|
||||
ACTIVITY_LOG.CREATE_TIME.as("createTime"),ACTIVITY_LOG.ACTIVITY_CONFIG_ID.as("activityConfigId")
|
||||
,ACTIVITY_LOG.ADDRESS.as("address"),ACTIVITY_LOG.TYPE.as("type")
|
||||
,ACTIVITY_LOG.AMOUNT.as("amount"),ACTIVITY_LOG.SUPERIOR_AMOUNT.as("superiorAmount"),ACTIVITY_LOG.SUPERIOR_ADDRESS.as("superiorAddress"),ACTIVITY_LOG.CONFIG_TYPE.as("configType")
|
||||
,ACTIVITY_LOG.MARK.as("mark"),T_MEMBER.TWITTER_ID.as("twitterId"))
|
||||
.from(ACTIVITY_LOG).leftJoin(T_MEMBER).on(
|
||||
ACTIVITY_LOG.ADDRESS.eq(T_MEMBER.ACCOUNT)).where(ACTIVITY_LOG.TYPE.eq(1)
|
||||
.and(ACTIVITY_LOG.CONFIG_TYPE.in(2,3,5))).fetchInto(TwitterTransshipmentDto.class);
|
||||
if(activityLogRecords == null || activityLogRecords.size() <= 0){
|
||||
return;
|
||||
}
|
||||
|
||||
//推文ID+推特ID == 点赞的用户
|
||||
Map<String,String> thumbsUpmap = new HashMap<>();
|
||||
{
|
||||
//点赞的推文id
|
||||
Set<String> thumbsUp = new HashSet<>();
|
||||
//推特ID == 用户地址
|
||||
Map<String,String> twitterMap = new HashMap<>();
|
||||
activityLogRecords.forEach(a -> {
|
||||
if(a.getConfigType().equals(3)){
|
||||
thumbsUp.add(a.getMark());
|
||||
twitterMap.put(a.getTwitterId(),a.getAddress());
|
||||
}
|
||||
});
|
||||
|
||||
for (String key : twitterMap.keySet()){
|
||||
String twId = key;
|
||||
String address = twitterMap.get(key);
|
||||
//查询出该推特用户 点赞了那些文章,返回推文的ID
|
||||
List<String> ids = twitterService.thumbsUpListByTwitterId(twId,TwitterConfig.getAccessToken(address));
|
||||
if(ids == null){
|
||||
continue;
|
||||
}
|
||||
//查询推特那些用户进行的点赞
|
||||
for (String id : ids){
|
||||
thumbsUpmap.put(id+twId,address);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//推文ID+推特ID == 转载的用户
|
||||
Map<String,String> transshipmentMap = new HashMap<>();
|
||||
{
|
||||
//转载的推文id
|
||||
Set<String> transshipment = new HashSet<>();
|
||||
activityLogRecords.forEach(a -> {
|
||||
if(a.getConfigType().equals(2)){
|
||||
transshipment.add(a.getMark());
|
||||
}
|
||||
});
|
||||
//查询推特那些用户进行的转载
|
||||
for (String twid : transshipment){
|
||||
List<TransshipmentUserDto> list = twitterService.transmitUserList(twid);
|
||||
if(list == null){
|
||||
continue;
|
||||
}
|
||||
list.forEach(t ->{
|
||||
transshipmentMap.put(twid+t.getId(),"1");
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
for (TwitterTransshipmentDto log : activityLogRecords){
|
||||
ActivityLogRecord logRecord = dslContext.newRecord(ACTIVITY_LOG);
|
||||
logRecord.setId(log.getId());
|
||||
if(log.getConfigType().equals(2)){
|
||||
//执行检查推文转载
|
||||
String value = transshipmentMap.get(log.getMark()+log.getTwitterId());
|
||||
logRecord.setType(value != null ? 2 : log.getType());
|
||||
}else if(log.getConfigType().equals(3)){
|
||||
String value = thumbsUpmap.get(log.getMark()+log.getTwitterId());
|
||||
logRecord.setType(value != null ? 2 : log.getType());
|
||||
}
|
||||
logRecord.setEndTime(new Timestamp(System.currentTimeMillis()));
|
||||
if(logRecord.getType() != null && logRecord.getType().equals(2)){
|
||||
//增加用户资产统计
|
||||
dslContext.update(ACTIVITY_STATISTICS).set(ACTIVITY_STATISTICS.AMOUNT,ACTIVITY_STATISTICS.AMOUNT.add(log.getAmount())).where(ACTIVITY_STATISTICS.ADDRESS.eq(log.getAddress())).execute();
|
||||
dslContext.update(ACTIVITY_STATISTICS).set(ACTIVITY_STATISTICS.AMOUNT,ACTIVITY_STATISTICS.AMOUNT.add(log.getSuperiorAmount())).where(ACTIVITY_STATISTICS.ADDRESS.eq(log.getSuperiorAddress())).execute();
|
||||
//更新数据
|
||||
logRecord.update();
|
||||
}else if(log.getType().equals(1) && DateUtils.addMinute(log.getCreateTime(),120).getTime() < System.currentTimeMillis()){
|
||||
//任务创建超过2小时,任务失败
|
||||
logRecord.setType(3);
|
||||
logRecord.update();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 加入Discord
|
||||
*/
|
||||
public void addDiscord() {
|
||||
List<DiscordTransshipmentDto> activityLogRecords = dslContext.select(ACTIVITY_LOG.ID.as("id"),ACTIVITY_LOG.ACTIVITY_CONFIG_ID.as("activityConfigId")
|
||||
,ACTIVITY_LOG.ADDRESS.as("address"),ACTIVITY_LOG.TYPE.as("type")
|
||||
,ACTIVITY_LOG.AMOUNT.as("amount"),ACTIVITY_LOG.CREATE_TIME.as("createTime"),ACTIVITY_LOG.SUPERIOR_AMOUNT.as("superiorAmount"),ACTIVITY_LOG.SUPERIOR_ADDRESS.as("superiorAddress"),
|
||||
ACTIVITY_LOG.CONFIG_TYPE.as("configType"),ACTIVITY_LOG.MARK.as("mark"),T_MEMBER.DISCORD_ID.as("discordId"))
|
||||
.from(ACTIVITY_LOG).leftJoin(T_MEMBER).on(
|
||||
ACTIVITY_LOG.ADDRESS.eq(T_MEMBER.ACCOUNT)).where(ACTIVITY_LOG.TYPE.eq(1)
|
||||
.and(ACTIVITY_LOG.CONFIG_TYPE.in(6))).fetchInto(DiscordTransshipmentDto.class);
|
||||
if(activityLogRecords == null || activityLogRecords.size() <= 0){
|
||||
return;
|
||||
}
|
||||
|
||||
for (DiscordTransshipmentDto log : activityLogRecords){
|
||||
ActivityLogRecord logRecord = dslContext.newRecord(ACTIVITY_LOG);
|
||||
logRecord.setId(log.getId());
|
||||
Boolean outcome = discordService.joinConfirmation(log.getAddress(), DiscordConfig.CHANNEL_ID);
|
||||
if(outcome){
|
||||
logRecord.setType(2);
|
||||
log.setType(2);
|
||||
}
|
||||
if(log.getType().equals(1) && DateUtils.addMinute(log.getCreateTime(),120).getTime() < System.currentTimeMillis()){
|
||||
//任务创建超过2小时,任务失败
|
||||
logRecord.setType(3);
|
||||
log.setType(3);
|
||||
}
|
||||
if(!log.getType().equals(1)){
|
||||
logRecord.update();
|
||||
}
|
||||
|
||||
if(log.getType().equals(2)){
|
||||
//增加用户资产统计
|
||||
dslContext.update(ACTIVITY_STATISTICS).set(ACTIVITY_STATISTICS.AMOUNT,ACTIVITY_STATISTICS.AMOUNT.add(log.getAmount())).where(ACTIVITY_STATISTICS.ADDRESS.eq(log.getAddress())).execute();
|
||||
dslContext.update(ACTIVITY_STATISTICS).set(ACTIVITY_STATISTICS.AMOUNT,ACTIVITY_STATISTICS.AMOUNT.add(log.getSuperiorAmount())).where(ACTIVITY_STATISTICS.ADDRESS.eq(log.getSuperiorAddress())).execute();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 乐观验证
|
||||
*/
|
||||
public void optimisticValidation() {
|
||||
List<ActivityLogRecord> logRecords = dslContext.select(ACTIVITY_LOG.ID,ACTIVITY_LOG.ADDRESS,ACTIVITY_LOG.AMOUNT,ACTIVITY_LOG.SUPERIOR_ADDRESS,ACTIVITY_LOG.SUPERIOR_AMOUNT).
|
||||
from(ACTIVITY_LOG).where(ACTIVITY_LOG.CONFIG_TYPE.in(4,7).and(ACTIVITY_LOG.TYPE.eq(1))).fetchInto(ActivityLogRecord.class);
|
||||
if(logRecords != null && logRecords.size() > 0){
|
||||
List<Integer> ids = new ArrayList<>();
|
||||
for (ActivityLogRecord log : logRecords){
|
||||
ids.add(log.getId());
|
||||
dslContext.update(ACTIVITY_STATISTICS).set(ACTIVITY_STATISTICS.AMOUNT,ACTIVITY_STATISTICS.AMOUNT.add(log.getAmount())).where(ACTIVITY_STATISTICS.ADDRESS.eq(log.getAddress())).execute();
|
||||
dslContext.update(ACTIVITY_STATISTICS).set(ACTIVITY_STATISTICS.AMOUNT,ACTIVITY_STATISTICS.AMOUNT.add(log.getSuperiorAmount())).where(ACTIVITY_STATISTICS.ADDRESS.eq(log.getSuperiorAddress())).execute();
|
||||
}
|
||||
dslContext.update(ACTIVITY_LOG).set(ACTIVITY_LOG.TYPE,2).where(ACTIVITY_LOG.ID.in(ids)).execute();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 加入TG
|
||||
*/
|
||||
public void addTg() {
|
||||
List<DiscordTransshipmentDto> activityLogRecords = dslContext.select(ACTIVITY_LOG.ID.as("id"),ACTIVITY_LOG.ACTIVITY_CONFIG_ID.as("activityConfigId")
|
||||
,ACTIVITY_LOG.ADDRESS.as("address"),ACTIVITY_LOG.TYPE.as("type")
|
||||
,ACTIVITY_LOG.AMOUNT.as("amount"),ACTIVITY_LOG.CREATE_TIME.as("createTime"),ACTIVITY_LOG.SUPERIOR_AMOUNT.as("superiorAmount"),ACTIVITY_LOG.SUPERIOR_ADDRESS.as("superiorAddress"),
|
||||
ACTIVITY_LOG.CONFIG_TYPE.as("configType"),ACTIVITY_LOG.MARK.as("mark"),T_MEMBER.TG_ID.as("tgId"))
|
||||
.from(ACTIVITY_LOG).leftJoin(T_MEMBER).on(
|
||||
ACTIVITY_LOG.ADDRESS.eq(T_MEMBER.ACCOUNT)).where(ACTIVITY_LOG.TYPE.eq(1)
|
||||
.and(ACTIVITY_LOG.CONFIG_TYPE.in(10))).fetchInto(DiscordTransshipmentDto.class);
|
||||
if(activityLogRecords == null || activityLogRecords.size() <= 0){
|
||||
return;
|
||||
}
|
||||
|
||||
for (DiscordTransshipmentDto log : activityLogRecords){
|
||||
ActivityLogRecord logRecord = dslContext.newRecord(ACTIVITY_LOG);
|
||||
logRecord.setId(log.getId());
|
||||
if(log.getTgId() != null){
|
||||
Boolean outcome = telegramServer.joinConfirmation(log.getTgId());
|
||||
if(outcome){
|
||||
logRecord.setType(2);
|
||||
log.setType(2);
|
||||
}
|
||||
}
|
||||
if(log.getType().equals(1) && DateUtils.addMinute(log.getCreateTime(),120).getTime() < System.currentTimeMillis()){
|
||||
//任务创建超过2小时,任务失败
|
||||
logRecord.setType(3);
|
||||
log.setType(3);
|
||||
}
|
||||
if(!log.getType().equals(1)){
|
||||
logRecord.update();
|
||||
}
|
||||
if(log.getType().equals(2)){
|
||||
//增加用户资产统计
|
||||
dslContext.update(ACTIVITY_STATISTICS).set(ACTIVITY_STATISTICS.AMOUNT,ACTIVITY_STATISTICS.AMOUNT.add(log.getAmount())).where(ACTIVITY_STATISTICS.ADDRESS.eq(log.getAddress())).execute();
|
||||
dslContext.update(ACTIVITY_STATISTICS).set(ACTIVITY_STATISTICS.AMOUNT,ACTIVITY_STATISTICS.AMOUNT.add(log.getSuperiorAmount())).where(ACTIVITY_STATISTICS.ADDRESS.eq(log.getSuperiorAddress())).execute();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,174 @@
|
|||
package com.alive.server.service;
|
||||
|
||||
import com.alive.server.config.TelegramConfig;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import lombok.var;
|
||||
import org.jooq.DSLContext;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.telegram.telegrambots.bots.TelegramLongPollingBot;
|
||||
import org.telegram.telegrambots.meta.api.methods.groupadministration.GetChatMember;
|
||||
import org.telegram.telegrambots.meta.api.methods.send.SendMessage;
|
||||
import org.telegram.telegrambots.meta.api.objects.Message;
|
||||
import org.telegram.telegrambots.meta.api.objects.Update;
|
||||
import org.telegram.telegrambots.meta.api.objects.chatmember.ChatMember;
|
||||
import org.telegram.telegrambots.meta.api.objects.replykeyboard.InlineKeyboardMarkup;
|
||||
import org.telegram.telegrambots.meta.api.objects.replykeyboard.buttons.InlineKeyboardButton;
|
||||
import org.telegram.telegrambots.meta.exceptions.TelegramApiException;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static com.alive.db.jooq.Tables.T_MEMBER;
|
||||
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
@Component
|
||||
public class TelegramServer extends TelegramLongPollingBot {
|
||||
|
||||
@Autowired
|
||||
private DSLContext dslContext;
|
||||
|
||||
@Autowired
|
||||
public TelegramServer(DSLContext dslContext) {
|
||||
this.dslContext = dslContext;
|
||||
}
|
||||
|
||||
private InlineKeyboardMarkup keyboardM1;
|
||||
|
||||
@Override
|
||||
public void onUpdateReceived(Update update) {
|
||||
var msg = update.getMessage();
|
||||
if(msg == null){
|
||||
return;
|
||||
}
|
||||
var user = msg.getFrom();
|
||||
//用户发送的消息,消息长度必须大于10以上 /start 0x505f87Bc247c907dc8005fC5d60d020Ae459CE09
|
||||
String text = msg.getText();
|
||||
if(user == null || text == null || text.length() < 10){
|
||||
return;
|
||||
}
|
||||
if (msg.getText().substring(0,6).equals("/start")) {
|
||||
//获取到用户的地址
|
||||
String address = msg.getText().substring(7,msg.getText().length()).toLowerCase();
|
||||
//获取到用户的TG id
|
||||
Long tgUserId = user.getId();
|
||||
String userAddress = dslContext.select(T_MEMBER.ACCOUNT).from(T_MEMBER).where(T_MEMBER.TG_ID.eq(tgUserId.toString())).limit(1).fetchAnyInto(String.class);
|
||||
if(userAddress != null){
|
||||
//该TG账号已经被绑定过了,绑定地址为: userAddress
|
||||
this.sendText(user.getId(),"Your account has been bound to an address 【"+userAddress+"】");
|
||||
return;
|
||||
}
|
||||
//开始绑定用户地址
|
||||
Integer outcome = dslContext.update(T_MEMBER).set(T_MEMBER.TG_ID,tgUserId.toString()).where(T_MEMBER.ACCOUNT.eq(address)).execute();
|
||||
if(outcome <= 0){
|
||||
//该账号不存在
|
||||
this.sendText(user.getId(),"The account is not registered");
|
||||
return;
|
||||
}
|
||||
InlineKeyboardButton joinUs = InlineKeyboardButton.builder()
|
||||
.text("加入我们")
|
||||
.url(TelegramConfig.ADD_TG_URL)
|
||||
.build();
|
||||
//此按钮 Tutorial 点击可以跳转到地址https://core.telegram.org/bots/api
|
||||
InlineKeyboardButton url = InlineKeyboardButton.builder()
|
||||
.text("官网链接")
|
||||
.url(TelegramConfig.APP_TG_URL)
|
||||
.build();
|
||||
List<InlineKeyboardButton> list = new ArrayList<>();
|
||||
list.add(joinUs);
|
||||
list.add(url);
|
||||
keyboardM1 = InlineKeyboardMarkup.builder()
|
||||
.keyboardRow(list).build();
|
||||
sendMenu(user.getId(), "<b>欢迎加入roos官网TG,请根据需求进行以下操作</b>",keyboardM1);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送消息到用户或者频道 后面是消息内容
|
||||
* @param id
|
||||
* @param txt
|
||||
* @param kb 消息下面跟着几个按钮可以点击的
|
||||
*/
|
||||
public void sendMenu(Long id, String txt, InlineKeyboardMarkup kb){
|
||||
SendMessage sm = SendMessage.builder().chatId(id.toString())
|
||||
.parseMode("HTML").text(txt)
|
||||
.replyMarkup(kb).build();
|
||||
|
||||
try {
|
||||
execute(sm);
|
||||
} catch (TelegramApiException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送消息到用户或者频道 后面是消息内容
|
||||
* @param id
|
||||
* @param msg
|
||||
*/
|
||||
private void scream(Long id, Message msg) {
|
||||
if(msg.hasText()){
|
||||
sendText(id, msg.getText().toLowerCase());
|
||||
} else{
|
||||
//copyMessage(id, msg.getMessageId()); //We can't really scream a sticker
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送消息到用户或者频道 后面是消息内容
|
||||
* @param id
|
||||
* @param what
|
||||
*/
|
||||
public void sendText(Long id, String what){
|
||||
SendMessage sm = SendMessage.builder()
|
||||
.chatId(id.toString())
|
||||
.text(what).build();
|
||||
try {
|
||||
execute(sm);
|
||||
} catch (TelegramApiException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getBotUsername() {
|
||||
// 返回您的机器人的用户名
|
||||
return TelegramConfig.TG_BOT_NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getBotToken() {
|
||||
// 返回您的机器人的令牌
|
||||
return TelegramConfig.TG_BOT_TOKEN;
|
||||
}
|
||||
|
||||
public Boolean joinConfirmation(String tgId) {
|
||||
// 处理接收到的消息 -1002019878988 6174699932
|
||||
// 创建一个 GetChatMembersCount 对象 5331549827
|
||||
// 使用 execute 方法发送请求并获取 ChatMembersCount 对象
|
||||
try { //创造者:creator 成员:member 未加入的:left left
|
||||
// 创建一个 GetChatMember 对象
|
||||
GetChatMember getChatMember = new GetChatMember(TelegramConfig.TG_BOT_TEAM_ID, Long.parseLong(tgId));
|
||||
// 使用 execute 方法发送请求并获取 ChatMember 对象
|
||||
ChatMember chatMember = execute(getChatMember);
|
||||
String status = chatMember.getStatus().toLowerCase();
|
||||
//Creator: 聊天创建者
|
||||
//Administrator: 管理员
|
||||
//Member: 普通成员
|
||||
//Restricted: 受限成员
|
||||
//Left: 已退出聊天
|
||||
//Kicked: 已踢出聊天
|
||||
if(status.equals("creator") || status.equals("administrator") || status.equals("member")){
|
||||
return true;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,114 @@
|
|||
package com.alive.server.service;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.web3j.abi.FunctionEncoder;
|
||||
import org.web3j.abi.TypeReference;
|
||||
import org.web3j.abi.datatypes.Address;
|
||||
import org.web3j.abi.datatypes.Function;
|
||||
import org.web3j.abi.datatypes.Type;
|
||||
import org.web3j.abi.datatypes.Uint;
|
||||
import org.web3j.abi.datatypes.generated.Uint256;
|
||||
import org.web3j.crypto.Credentials;
|
||||
import org.web3j.crypto.RawTransaction;
|
||||
import org.web3j.crypto.TransactionEncoder;
|
||||
import org.web3j.protocol.Web3j;
|
||||
import org.web3j.protocol.core.DefaultBlockParameterName;
|
||||
import org.web3j.protocol.core.methods.request.Transaction;
|
||||
import org.web3j.protocol.core.methods.response.EthEstimateGas;
|
||||
import org.web3j.protocol.core.methods.response.EthGetTransactionReceipt;
|
||||
import org.web3j.protocol.core.methods.response.EthSendTransaction;
|
||||
import org.web3j.protocol.core.methods.response.TransactionReceipt;
|
||||
import org.web3j.protocol.http.HttpService;
|
||||
import org.web3j.tx.gas.ContractGasProvider;
|
||||
import org.web3j.tx.gas.DefaultGasProvider;
|
||||
import org.web3j.utils.Numeric;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
@Component
|
||||
public class TokenTransferServer {
|
||||
|
||||
/**
|
||||
* 节点的 RPC URL
|
||||
*/
|
||||
@Value("${chain.transfer.rpcUrl}")
|
||||
private String rpcUrl;
|
||||
|
||||
/**
|
||||
* ERC-20代币合约地址
|
||||
*/
|
||||
@Value("${chain.transfer.erc20}")
|
||||
private String contractAddress;
|
||||
|
||||
/**
|
||||
* 发送方的私钥
|
||||
*/
|
||||
@Value("${chain.transfer.privateKey}")
|
||||
private String privateKey;
|
||||
|
||||
|
||||
/**
|
||||
* ERC20转账到指定地址
|
||||
* @param amount
|
||||
* @param toAddress
|
||||
*/
|
||||
public String transferTo(BigDecimal amount, String toAddress, Integer non) {
|
||||
try {
|
||||
Web3j web3j = Web3j.build(new HttpService(rpcUrl));
|
||||
Credentials credentials = Credentials.create(privateKey);
|
||||
Function function = new Function(
|
||||
"transfer",
|
||||
Arrays.asList(new Address(toAddress), new Uint256(amount.toBigInteger())),
|
||||
Collections.emptyList()
|
||||
);
|
||||
String encodedFunction = FunctionEncoder.encode(function);
|
||||
BigInteger gasLimit = BigInteger.valueOf(21000);
|
||||
BigInteger nonce = web3j.ethGetTransactionCount(credentials.getAddress(), DefaultBlockParameterName.PENDING).send().getTransactionCount().add(new BigInteger(non.toString()));
|
||||
BigInteger gasPrice = web3j.ethGasPrice().send().getGasPrice();
|
||||
RawTransaction rawTransaction = RawTransaction.createTransaction(
|
||||
nonce,
|
||||
gasPrice,
|
||||
gasLimit,
|
||||
contractAddress,
|
||||
encodedFunction
|
||||
);
|
||||
byte[] signedMessage = TransactionEncoder.signMessage(rawTransaction, credentials);
|
||||
String hexValue = Numeric.toHexString(signedMessage);
|
||||
EthSendTransaction ethSendTransaction = web3j.ethSendRawTransaction(hexValue).send();
|
||||
if (ethSendTransaction.hasError()) {
|
||||
if(ethSendTransaction.getError().getMessage().equals("nonce too low")){
|
||||
return this.transferTo(amount, toAddress, non + 1);
|
||||
} else {
|
||||
log.error("Token transfer failed. Error: {}", ethSendTransaction.getError().getMessage());
|
||||
}
|
||||
} else {
|
||||
String transactionHash = ethSendTransaction.getTransactionHash();
|
||||
// 等待交易确认3秒,不然nonce确认不过来,会导致错误
|
||||
Thread.sleep(3000);
|
||||
EthGetTransactionReceipt receipt = web3j.ethGetTransactionReceipt(transactionHash).send();
|
||||
if (receipt.getTransactionReceipt().isPresent()) {
|
||||
log.info("Transaction confirmed. Hash: {}", transactionHash);
|
||||
} else {
|
||||
log.warn("Transaction might not be confirmed yet. Hash: {}", transactionHash);
|
||||
}
|
||||
return transactionHash;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("ERC20转账错误: {}", e.getMessage());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,633 @@
|
|||
package com.alive.server.service;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.alive.server.dto.AttentionDto;
|
||||
import com.alive.server.dto.TransshipmentUserDto;
|
||||
import com.alive.server.dto.TwitterDto;
|
||||
import com.alive.server.dto.TwitterUserDto;
|
||||
import com.alive.commons.config.BaseComponent;
|
||||
import com.alive.server.config.TwitterConfig;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import oauth.signpost.commonshttp.CommonsHttpOAuthConsumer;
|
||||
import oauth.signpost.exception.OAuthCommunicationException;
|
||||
import oauth.signpost.exception.OAuthExpectationFailedException;
|
||||
import oauth.signpost.exception.OAuthMessageSignerException;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.NameValuePair;
|
||||
import org.apache.http.client.HttpClient;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.apache.http.client.utils.URIBuilder;
|
||||
import org.apache.http.impl.client.HttpClientBuilder;
|
||||
import org.apache.http.message.BasicNameValuePair;
|
||||
import org.apache.http.util.EntityUtils;
|
||||
import org.jooq.DSLContext;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.*;
|
||||
import java.util.*;
|
||||
|
||||
import static com.alive.db.jooq.Tables.T_MEMBER;
|
||||
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
public class TwitterService extends BaseComponent {
|
||||
|
||||
@Autowired
|
||||
private DSLContext dslContext;
|
||||
|
||||
public static String codeChallenge = "0ioze5m20493ny2";
|
||||
|
||||
/**
|
||||
* 生成推文转发链接
|
||||
* @param authorizationReq
|
||||
* @return
|
||||
*/
|
||||
/* public String getTtTweetsUrl(TwitterAuthorizationReq authorizationReq){
|
||||
String url = "https://twitter.com/";
|
||||
MerchantPojo merchantPojo = merchantService.getMerchant(authorizationReq.getCodeNo(),authorizationReq.getMerchantOn());
|
||||
MerchantConfigPojo merchantConfigPojo = merchantService.getMerchantConfig(merchantPojo.getId());
|
||||
url += merchantConfigPojo.getTtUserName();
|
||||
url += "/status/" + merchantConfigPojo.getTtTweetsId() +"?s=20";
|
||||
return url;
|
||||
}*/
|
||||
|
||||
/**
|
||||
* 返回授权的地址
|
||||
* @param address
|
||||
* @return
|
||||
*/
|
||||
public String getAuthorizationUrl(String address){
|
||||
String url = "https://twitter.com/i/oauth2/authorize?";
|
||||
url += "client_id="+ TwitterConfig.CLIENT_ID;
|
||||
//访问权限
|
||||
url += "&scope="+ "tweet.read%20tweet.write%20offline.access%20tweet.moderate.write%20users.read%20follows.read%20follows.write%20like.read";
|
||||
url += "&response_type=code";
|
||||
//回调地址
|
||||
url += "&redirect_uri="+TwitterConfig.CALLBACK_URL;
|
||||
//用户地址
|
||||
url += "&state="+address;
|
||||
url += "&code_challenge="+codeChallenge+"&code_challenge_method=plain";
|
||||
return url;
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户关注
|
||||
* @param token 授权换取的用户token
|
||||
* @param userId 用户自己的ID
|
||||
* @param targetUserId 被关注的推特用户ID
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
public AttentionDto attention(String token, String userId, String targetUserId) {
|
||||
try {
|
||||
String urlAdress = "https://api.twitter.com/2/users/" + userId + "/following";
|
||||
URL url12 = new URL(urlAdress);
|
||||
HttpURLConnection connection = (HttpURLConnection) url12.openConnection();
|
||||
connection.setRequestMethod("POST");
|
||||
connection.setRequestProperty("Content-Type", "application/json");
|
||||
connection.setRequestProperty("Authorization", "Bearer " + token);
|
||||
JSONObject requestBody = new JSONObject();
|
||||
//需要关注的用户ID
|
||||
requestBody.put("target_user_id", targetUserId);
|
||||
String requestBodyString = requestBody.toString();
|
||||
connection.setDoOutput(true);
|
||||
OutputStream outputStream = connection.getOutputStream();
|
||||
outputStream.write(requestBodyString.getBytes());
|
||||
outputStream.flush();
|
||||
outputStream.close();
|
||||
|
||||
int responseCode = connection.getResponseCode();
|
||||
InputStream inputStream;
|
||||
if (responseCode == 429) {
|
||||
Assert.notNull(null, "limiting frequency");
|
||||
}
|
||||
if (responseCode >= 200 && responseCode < 400) {
|
||||
inputStream = connection.getInputStream();
|
||||
} else {
|
||||
inputStream = connection.getErrorStream();
|
||||
}
|
||||
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
|
||||
String line;
|
||||
StringBuilder responseBuilder = new StringBuilder();
|
||||
while ((line = reader.readLine()) != null) {
|
||||
responseBuilder.append(line);
|
||||
}
|
||||
reader.close();
|
||||
String response = responseBuilder.toString();
|
||||
if (JSON.parseObject(response).get("data") != null) {
|
||||
JSONObject json = JSON.parseObject(JSON.parseObject(response).get("data").toString());
|
||||
AttentionDto attentionDto = new AttentionDto();
|
||||
Object ret = json.get("following");
|
||||
attentionDto.setFollowing(Boolean.parseBoolean(ret == null ? "false" : ret.toString()));
|
||||
ret = json.get("pending_follow");
|
||||
attentionDto.setPending_follow(Boolean.parseBoolean(ret == null ? "false" : ret.toString()));
|
||||
return attentionDto;
|
||||
}
|
||||
return null;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据code获取用户token
|
||||
* @param address 授权地址
|
||||
* @param code 获取token
|
||||
* @return
|
||||
*/
|
||||
public TwitterDto requestBearerToken(String address, String code) {
|
||||
try {
|
||||
TwitterDto twitterDto = new TwitterDto();
|
||||
String clientId = URLEncoder.encode(TwitterConfig.CLIENT_ID, "UTF-8");
|
||||
String clientSecret = URLEncoder.encode(TwitterConfig.CLIENT_SECRET, "UTF-8");
|
||||
String credentials = clientId + ":" + clientSecret;
|
||||
String base64Credentials = Base64.getEncoder().encodeToString(credentials.getBytes());
|
||||
|
||||
String redirectURI = TwitterConfig.CALLBACK_URL;
|
||||
URL url = new URL("https://api.twitter.com/2/oauth2/token");
|
||||
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
|
||||
connection.setRequestMethod("POST");
|
||||
connection.setRequestProperty("Authorization", "Basic " + base64Credentials);
|
||||
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8");
|
||||
connection.setDoOutput(true);
|
||||
connection.setDoInput(true);
|
||||
String data = "";
|
||||
String refreshToken = TwitterConfig.getRefreshToken(address);
|
||||
String accessToken = TwitterConfig.getAccessToken(address);
|
||||
if(!StringUtils.isBlank(refreshToken) && !StringUtils.isBlank(accessToken)){
|
||||
//避免用户重复获取token
|
||||
twitterDto.setAccessToken(accessToken);
|
||||
twitterDto.setRefreshToken(refreshToken);
|
||||
return twitterDto;
|
||||
}
|
||||
if(StringUtils.isBlank(refreshToken) && code == null){
|
||||
return null;
|
||||
}
|
||||
if(StringUtils.isBlank(refreshToken) && code != null){
|
||||
String grantType = "authorization_code";
|
||||
//获取令牌需要的参数 code_verifier 需要和获取code传入参数 code_challenge 保持一致
|
||||
data = "grant_type=" + grantType + "&code=" + code + "&redirect_uri=" + redirectURI+
|
||||
"&client_id="+TwitterConfig.CLIENT_ID+"&client_secret="+TwitterConfig.CLIENT_SECRET+"&code_verifier="+codeChallenge;
|
||||
}else{
|
||||
String grantType = "refresh_token";
|
||||
//刷新令牌需要的参数
|
||||
data = "refresh_token="+refreshToken+"&grant_type=" + grantType + "&client_id="+TwitterConfig.CLIENT_ID+
|
||||
"&client_secret="+TwitterConfig.CLIENT_SECRET+"&code_verifier="+codeChallenge;
|
||||
}
|
||||
connection.getOutputStream().write(data.getBytes("UTF-8"));
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
|
||||
StringBuilder response = new StringBuilder();
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
response.append(line);
|
||||
}
|
||||
reader.close();
|
||||
String jsonResponse = response.toString();
|
||||
JSONObject json = JSON.parseObject(jsonResponse);
|
||||
accessToken = json.getString("access_token");
|
||||
twitterDto.setAccessToken(accessToken == null ? null : accessToken);
|
||||
refreshToken = json.getString("refresh_token");
|
||||
twitterDto.setRefreshToken(refreshToken == null ? null : refreshToken);
|
||||
|
||||
TwitterConfig.addAccessToken(address,accessToken,6000);
|
||||
TwitterConfig.addRefreshToken(address,refreshToken,60 * 60 * 168);
|
||||
return twitterDto;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取开发者推特token
|
||||
* @return
|
||||
*/
|
||||
public String getTwitterToken(){
|
||||
try {
|
||||
String consumerKey = URLEncoder.encode(TwitterConfig.CONSUMER_KEY, "UTF-8");
|
||||
String consumerSecret = URLEncoder.encode(TwitterConfig.CONSUMER_SECRET, "UTF-8");
|
||||
String credentials = consumerKey + ":" + consumerSecret;
|
||||
String base64Credentials = Base64.getEncoder().encodeToString(credentials.getBytes());
|
||||
//authorization_code、refresh_token、client_credentials
|
||||
String grantType = "client_credentials";
|
||||
URL url = new URL("https://api.twitter.com/oauth2/token");
|
||||
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
|
||||
connection.setRequestMethod("POST");
|
||||
connection.setRequestProperty("Authorization", "Basic " + base64Credentials);
|
||||
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8");
|
||||
connection.setDoOutput(true);
|
||||
connection.setDoInput(true);
|
||||
String data = "grant_type=" + grantType +
|
||||
"&client_id="+TwitterConfig.CLIENT_ID+"&client_secret="+TwitterConfig.CLIENT_SECRET+"&code_verifier=challenge";
|
||||
connection.getOutputStream().write(data.getBytes("UTF-8"));
|
||||
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
|
||||
StringBuilder response = new StringBuilder();
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
response.append(line);
|
||||
}
|
||||
reader.close();
|
||||
|
||||
// Extract bearer token from JSON response
|
||||
String jsonResponse = response.toString();
|
||||
JSONObject json = JSON.parseObject(jsonResponse);
|
||||
return json.get("access_token").toString();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取开发者账号信息
|
||||
* @return
|
||||
*/
|
||||
public JSONObject getUserInfo() throws Exception {
|
||||
CommonsHttpOAuthConsumer consumer = new CommonsHttpOAuthConsumer(TwitterConfig.CONSUMER_KEY, TwitterConfig.CONSUMER_SECRET);
|
||||
consumer.setTokenWithSecret(TwitterConfig.ACCESS_TOKEN, TwitterConfig.ACCESS_TOKEN_SECRET);
|
||||
// 创建HttpClient对象
|
||||
HttpClient httpClient = this.setProxy();
|
||||
// 创建API请求,例如获取用户的时间线
|
||||
try {
|
||||
URIBuilder uriBuilder = new URIBuilder("https://api.twitter.com/2/users/me");
|
||||
ArrayList<NameValuePair> queryParameters;
|
||||
queryParameters = new ArrayList<>();
|
||||
queryParameters.add(new BasicNameValuePair("user.fields", "id,name,username,profile_image_url,public_metrics"));
|
||||
queryParameters.add(new BasicNameValuePair("expansions", "pinned_tweet_id"));
|
||||
uriBuilder.addParameters(queryParameters);
|
||||
HttpGet request = new HttpGet(uriBuilder.build());
|
||||
request.setHeader("Content-Type","application/json");
|
||||
consumer.sign(request);
|
||||
// 创建参数列表
|
||||
HttpResponse response = httpClient.execute(request);
|
||||
// 处理API响应
|
||||
int statusCode = response.getStatusLine().getStatusCode();
|
||||
String responseBody = EntityUtils.toString(response.getEntity());
|
||||
if (statusCode == 200) {
|
||||
System.out.println(responseBody);
|
||||
return JSONObject.parseObject(responseBody);
|
||||
} else {
|
||||
System.out.println(responseBody);
|
||||
return JSONObject.parseObject(responseBody);
|
||||
}
|
||||
} catch (OAuthMessageSignerException e) {
|
||||
e.printStackTrace();
|
||||
} catch (OAuthExpectationFailedException e) {
|
||||
e.printStackTrace();
|
||||
} catch (OAuthCommunicationException e) {
|
||||
e.printStackTrace();
|
||||
} catch (URISyntaxException e) {
|
||||
e.printStackTrace();
|
||||
}catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置请求代理
|
||||
* @return
|
||||
*/
|
||||
private HttpClient setProxy(){
|
||||
// 创建HttpClientBuilder对象
|
||||
HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
|
||||
HttpClient client = httpClientBuilder.build();;
|
||||
return client;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 根据用户token换取用户信息
|
||||
* @param token
|
||||
* @return
|
||||
*/
|
||||
public TwitterUserDto getUserInfoByToken(String token){
|
||||
StringBuilder result = new StringBuilder();
|
||||
BufferedReader in = null;
|
||||
try {
|
||||
// Twitter API endpoint
|
||||
String endpoint = "https://api.twitter.com/2/users/me";
|
||||
// 构造带有参数的 URL
|
||||
String urlWithParams = endpoint + "?user.fields=name,pinned_tweet_id,profile_image_url";
|
||||
// 创建 URL 对象
|
||||
URL url = new URL(urlWithParams);
|
||||
URLConnection connection = url.openConnection();
|
||||
connection.setRequestProperty("Authorization", "Bearer " + token);
|
||||
connection.setRequestProperty("Content-Type","application/json");
|
||||
connection.connect();
|
||||
in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
|
||||
String line;
|
||||
while ((line = in.readLine()) != null)
|
||||
{
|
||||
result.append(line);
|
||||
}
|
||||
TwitterUserDto dto = new TwitterUserDto();
|
||||
JSONObject json = JSONObject.parseObject(result.toString());
|
||||
JSONObject user = (JSONObject)json.get("data");
|
||||
if(user != null){
|
||||
dto.setId(user.get("id").toString());
|
||||
dto.setName(user.get("name").toString());
|
||||
dto.setImg(user.get("profile_image_url").toString());
|
||||
dto.setUsername(user.get("username").toString());
|
||||
}
|
||||
return dto;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 换取token查询用户信息
|
||||
* @param address
|
||||
*/
|
||||
public TwitterUserDto getTwitterToken(String address,String token) {
|
||||
TwitterUserDto twitterUserDto = this.getUserInfoByToken(token);
|
||||
Assert.notNull(twitterUserDto, "get twitter user error");
|
||||
return twitterUserDto;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据推文ID查询那些用户进行了转发
|
||||
* @param tweetId
|
||||
* @return
|
||||
*/
|
||||
public List<TransshipmentUserDto> transmitUserList(String tweetId){
|
||||
CommonsHttpOAuthConsumer consumer = new CommonsHttpOAuthConsumer(TwitterConfig.CONSUMER_KEY, TwitterConfig.CONSUMER_SECRET);
|
||||
consumer.setTokenWithSecret(TwitterConfig.ACCESS_TOKEN, TwitterConfig.ACCESS_TOKEN_SECRET);
|
||||
// 创建HttpClient对象
|
||||
HttpClient httpClient = this.setProxy();
|
||||
// 创建API请求,例如获取用户的时间线
|
||||
try {
|
||||
URIBuilder uriBuilder = new URIBuilder("https://api.twitter.com/2/tweets/"+tweetId+"/retweeted_by");
|
||||
HttpGet request = new HttpGet(uriBuilder.build());
|
||||
request.setHeader("Content-Type","application/json");
|
||||
consumer.sign(request);
|
||||
// 创建参数列表
|
||||
HttpResponse response = httpClient.execute(request);
|
||||
// 处理API响应
|
||||
int statusCode = response.getStatusLine().getStatusCode();
|
||||
String responseBody = EntityUtils.toString(response.getEntity());
|
||||
if (statusCode == HttpURLConnection.HTTP_OK) {
|
||||
List<TransshipmentUserDto> list = new ArrayList<>();
|
||||
// 读取响应
|
||||
//默认最大返回100条
|
||||
JSONObject array = JSONObject.parseObject(responseBody);
|
||||
JSONArray arr = array.getJSONArray("data");
|
||||
if(arr == null){
|
||||
return list;
|
||||
}
|
||||
for (int i = 0; i < arr.size(); i++) {
|
||||
list.add(arr.getObject(i,TransshipmentUserDto.class));
|
||||
}
|
||||
// 打印响应
|
||||
return list;
|
||||
} else {
|
||||
System.out.println("Failed to fetch data from Twitter API. Response code: " + statusCode);
|
||||
}
|
||||
} catch (OAuthMessageSignerException e) {
|
||||
e.printStackTrace();
|
||||
} catch (OAuthExpectationFailedException e) {
|
||||
e.printStackTrace();
|
||||
} catch (OAuthCommunicationException e) {
|
||||
e.printStackTrace();
|
||||
} catch (URISyntaxException e) {
|
||||
e.printStackTrace();
|
||||
}catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据用户token和用户ID查询用户喜欢的推文
|
||||
* @param token
|
||||
* @return
|
||||
*/
|
||||
public List<String> thumbsUpListByTwitterId(String twitterId, String token){
|
||||
if(twitterId == null || token == null){
|
||||
return null;
|
||||
}
|
||||
StringBuilder result = new StringBuilder();
|
||||
BufferedReader in = null;
|
||||
try {
|
||||
// Twitter API endpoint
|
||||
String endpoint = "https://api.twitter.com/2/users/"+twitterId+"/liked_tweets";
|
||||
// 构造带有参数的 URL
|
||||
String urlWithParams = endpoint + "?expansions=edit_history_tweet_ids,referenced_tweets.id";
|
||||
// 创建 URL 对象
|
||||
URL url = new URL(urlWithParams);
|
||||
URLConnection connection = url.openConnection();
|
||||
connection.setRequestProperty("Authorization", "Bearer " + token);
|
||||
connection.setRequestProperty("Content-Type","application/json");
|
||||
connection.connect();
|
||||
in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
|
||||
String line;
|
||||
while ((line = in.readLine()) != null)
|
||||
{
|
||||
result.append(line);
|
||||
}
|
||||
List<String> list = new ArrayList<>();
|
||||
JSONObject json = JSONObject.parseObject(result.toString());
|
||||
JSONArray twittList = json.getJSONArray("data");
|
||||
if(twittList != null && twittList.size() > 0){
|
||||
for (int i = 0; i < twittList.size(); i++) {
|
||||
JSONObject twitt = twittList.getJSONObject(i);
|
||||
list.add(twitt.getString("id"));
|
||||
}
|
||||
return list;
|
||||
}
|
||||
return null;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据推文ID查询那些用户进行了点赞
|
||||
* @param tweetId
|
||||
* @return
|
||||
*/
|
||||
public List<TransshipmentUserDto> thumbsUpList(String tweetId){
|
||||
CommonsHttpOAuthConsumer consumer = new CommonsHttpOAuthConsumer(TwitterConfig.CONSUMER_KEY, TwitterConfig.CONSUMER_SECRET);
|
||||
consumer.setTokenWithSecret(TwitterConfig.ACCESS_TOKEN, TwitterConfig.ACCESS_TOKEN_SECRET);
|
||||
// 创建HttpClient对象
|
||||
HttpClient httpClient = this.setProxy();
|
||||
// 创建API请求,例如获取用户的时间线
|
||||
try {
|
||||
URIBuilder uriBuilder = new URIBuilder("https://api.twitter.com/2/tweets/"+tweetId+"/liking_users");
|
||||
HttpGet request = new HttpGet(uriBuilder.build());
|
||||
request.setHeader("Content-Type","application/json");
|
||||
consumer.sign(request);
|
||||
// 创建参数列表
|
||||
HttpResponse response = httpClient.execute(request);
|
||||
// 处理API响应
|
||||
int statusCode = response.getStatusLine().getStatusCode();
|
||||
String responseBody = EntityUtils.toString(response.getEntity());
|
||||
if (statusCode == HttpURLConnection.HTTP_OK) {
|
||||
// 读取响应
|
||||
//默认最大返回100条
|
||||
JSONObject array = JSONObject.parseObject(responseBody);
|
||||
JSONArray arr = array.getJSONArray("data");
|
||||
List<TransshipmentUserDto> list = new ArrayList<>();
|
||||
for (int i = 0; i < arr.size(); i++) {
|
||||
list.add(arr.getObject(i,TransshipmentUserDto.class));
|
||||
}
|
||||
// 打印响应
|
||||
return list;
|
||||
} else {
|
||||
System.out.println("Failed to fetch data from Twitter API. Response code: " + statusCode);
|
||||
}
|
||||
} catch (OAuthMessageSignerException e) {
|
||||
e.printStackTrace();
|
||||
} catch (OAuthExpectationFailedException e) {
|
||||
e.printStackTrace();
|
||||
} catch (OAuthCommunicationException e) {
|
||||
e.printStackTrace();
|
||||
} catch (URISyntaxException e) {
|
||||
e.printStackTrace();
|
||||
}catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void bindUser(String id) {
|
||||
Integer num = dslContext.selectCount().from(T_MEMBER).where(T_MEMBER.TWITTER_ID.eq(id)).fetchAnyInto(Integer.class);
|
||||
Assert.isTrue(num == 0,"The account has been linked Twitter");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 查询我的推文列表
|
||||
* @param tweetUserId
|
||||
* @param token
|
||||
* @param ttTweetsId 平台指定转推文的ID
|
||||
* @param maxResults = 5-10之间
|
||||
* @return
|
||||
|
||||
public Integer getTweetList(String tweetUserId,String token,Integer maxResults,String ttTweetsId){
|
||||
try {
|
||||
String httpUrl = "https://api.twitter.com/2/users/"+ tweetUserId + "/tweets?max_results="+maxResults;
|
||||
httpUrl += "&expansions=author_id,edit_history_tweet_ids,referenced_tweets.id&tweet.fields=created_at";
|
||||
// 只查用户当日的推文
|
||||
Instant currentTime = LocalDateTime.of(LocalDate.now(), LocalTime.MIN).toInstant(ZoneOffset.of("+8"));
|
||||
DateTimeFormatter formatter = DateTimeFormatter.ISO_INSTANT;
|
||||
String endTimeRFC3339 = formatter.format(currentTime);
|
||||
httpUrl += "&start_time="+endTimeRFC3339;
|
||||
// 构建请求 URL
|
||||
URL url = new URL(httpUrl);
|
||||
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
|
||||
// 设置请求方法和请求头
|
||||
connection.setRequestMethod("GET");
|
||||
connection.setRequestProperty("Authorization", "Bearer " + token);
|
||||
// 发送请求
|
||||
int responseCode = connection.getResponseCode();
|
||||
Assert.isTrue(responseCode == HttpURLConnection.HTTP_OK, "get tweet error");
|
||||
Integer numer = 0;
|
||||
// 读取响应
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
|
||||
String line;
|
||||
StringBuilder response = new StringBuilder();
|
||||
while ((line = reader.readLine()) != null) {
|
||||
response.append(line);
|
||||
}
|
||||
reader.close();
|
||||
JSONObject jsonObject = JSON.parseObject(response.toString());
|
||||
JSONArray jsonArray = (JSONArray) jsonObject.get("data");
|
||||
if(jsonArray == null){
|
||||
return numer;
|
||||
}
|
||||
for (int i = 0; i < jsonArray.size(); i++) {
|
||||
JSONObject json = jsonArray.getJSONObject(i);
|
||||
JSONArray referencedTweets = json.getJSONArray("referenced_tweets");
|
||||
if(referencedTweets != null){
|
||||
retweeted: 表示当前推文是转推(Retweet)的引用。
|
||||
quoted: 表示当前推文是引用推文(Quote Tweet)的引用。
|
||||
replied_to: 表示当前推文是回复(Reply)的引用。
|
||||
//上个推文的id
|
||||
String type = referencedTweets.getJSONObject(0).get("type").toString();
|
||||
String id = referencedTweets.getJSONObject(0).get("id").toString();
|
||||
if(type.equals("quoted") || type.equals("retweeted") && ttTweetsId.equals(id)){
|
||||
//quoted 表示推文是引用
|
||||
numer++;
|
||||
}
|
||||
}
|
||||
}
|
||||
// 打印响应
|
||||
return numer;
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return 0;
|
||||
}*/
|
||||
|
||||
/*private String getFollowers(String url_with_cursor) {
|
||||
String tweetResponse = null;
|
||||
HttpClient httpClient = HttpClients.custom()
|
||||
.setDefaultRequestConfig(RequestConfig.custom()
|
||||
.setCookieSpec(CookieSpecs.STANDARD).build())
|
||||
.build();
|
||||
try {
|
||||
URIBuilder uriBuilder = new URIBuilder(url_with_cursor);
|
||||
ArrayList<NameValuePair> queryParameters = new ArrayList<>();
|
||||
queryParameters.add(new BasicNameValuePair("user.fields", "username"));
|
||||
uriBuilder.addParameters(queryParameters);
|
||||
|
||||
HttpGet httpGet = new HttpGet(uriBuilder.build());
|
||||
httpGet.setHeader("Authorization", String.format("Bearer %s", "T2xwaGZOazRBbW9USWluSmpueUIwNW51MXhGa1dzWkpWTkgzOFJCdTRyRHNlOjE3MTAzMTk0MDM4NDU6MToxOmF0OjE"));
|
||||
httpGet.setHeader("Content-Type", "application/json");
|
||||
|
||||
HttpResponse response = httpClient.execute(httpGet);
|
||||
HttpEntity entity = response.getEntity();
|
||||
if (null != entity) {
|
||||
tweetResponse = EntityUtils.toString(entity, "UTF-8");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return tweetResponse;
|
||||
}*/
|
||||
|
||||
/**
|
||||
* 查询用户推文列表
|
||||
* @param setCodeNo
|
||||
* @return
|
||||
|
||||
public TgUserReq findChannelMember(AttentionReq setCodeNo) {
|
||||
String tweetNumber = "tweet_list"+setCodeNo.getAddress();
|
||||
String value = RedisUtil.get(tweetNumber);
|
||||
if(value != null){
|
||||
return new TgUserReq().setTwitterNumber(Integer.parseInt(value));
|
||||
}
|
||||
String userId = RedisUtil.get("twitter_user"+setCodeNo.getAddress());
|
||||
String tokenKey = RedisUtil.get("twitter_token" + setCodeNo.getAddress());
|
||||
MerchantPojo merchantPojo = merchantService.getMerchant(setCodeNo.getCodeNo(),setCodeNo.getMerchantOn());
|
||||
MerchantConfigPojo merchantConfigPojo = merchantService.getMerchantConfig(merchantPojo.getId());
|
||||
Integer num = this.getTweetList(userId,tokenKey,100,merchantConfigPojo.getTtTweetsId());
|
||||
if(num > 0){
|
||||
TaskLogRecord memberRecord = dslContext.selectFrom(TASK_LOG).where(TASK_LOG.STATUS.eq(1).and(TASK_LOG.ADDRESS.eq(setCodeNo.getAddress()))
|
||||
.and(TASK_LOG.TASK_TYPE.eq(1))
|
||||
.and(TASK_LOG.CREATE_TIME.between(new Timestamp(com.ruoyi.common.utils.DateUtils.getStartDate(new Date()).getTime()),new Timestamp(com.ruoyi.common.utils.DateUtils.getFinallyDate(new Date()).getTime())))).fetchAny();
|
||||
if(memberRecord != null){
|
||||
memberRecord.setTaskType(3);
|
||||
memberRecord.store();
|
||||
}
|
||||
}
|
||||
RedisUtil.setEx(tweetNumber,num.toString(),60 * 5);
|
||||
return new TgUserReq().setTwitterNumber(num);
|
||||
}*/
|
||||
}
|
|
@ -0,0 +1,178 @@
|
|||
package com.alive.server.service;
|
||||
|
||||
import com.alive.commons.config.BaseComponent;
|
||||
import com.alive.commons.enums.WalletLogTypeEnum;
|
||||
import com.alive.commons.util.CoinUtil;
|
||||
import com.alive.db.jooq.tables.records.ActivityStatisticsRecord;
|
||||
import com.alive.db.jooq.tables.records.CoinConfigRecord;
|
||||
import com.alive.db.jooq.tables.records.TMemberWalletRecord;
|
||||
import com.alive.server.dto.WalletOperation;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static com.alive.db.jooq.Tables.*;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
public class WalletService extends BaseComponent {
|
||||
|
||||
@Autowired
|
||||
private WalletService walletService;
|
||||
|
||||
public void initWallet(int memberId,String address) {
|
||||
//实例化用户资产统计
|
||||
ActivityStatisticsRecord statisticsRecord = dslContext.newRecord(ACTIVITY_STATISTICS);
|
||||
statisticsRecord.setAddress(address);
|
||||
statisticsRecord.setAmount(BigDecimal.ZERO);
|
||||
statisticsRecord.store();
|
||||
|
||||
List<CoinConfigRecord> configRecords = dslContext.select().from(COIN_CONFIG).fetchInto(CoinConfigRecord.class);
|
||||
for (CoinConfigRecord configRecord : configRecords) {
|
||||
TMemberWalletRecord walletRecord = dslContext.newRecord(T_MEMBER_WALLET);
|
||||
walletRecord.setCoinId(configRecord.getId());
|
||||
walletRecord.setBalance(BigDecimal.ZERO);
|
||||
walletRecord.setMemberId(memberId);
|
||||
walletRecord.store();
|
||||
/*if (!env.equals("prod")) {
|
||||
BigDecimal gift = BigDecimal.valueOf(10000L);
|
||||
operateBalance(walletRecord.getId(), WalletLogTypeEnum.ADMIN_ADD, gift, null);
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
||||
public TMemberWalletRecord getWallet(int walletId) {
|
||||
TMemberWalletRecord walletRecord = dslContext.fetchOne(T_MEMBER_WALLET, T_MEMBER_WALLET.ID.eq(walletId));
|
||||
return walletRecord;
|
||||
}
|
||||
|
||||
public TMemberWalletRecord getWallet(Integer memberId, int coinId) {
|
||||
if (memberId == null) {
|
||||
return null;
|
||||
}
|
||||
TMemberWalletRecord walletRecord = dslContext.selectFrom(T_MEMBER_WALLET).where(T_MEMBER_WALLET.MEMBER_ID.eq(memberId).and(T_MEMBER_WALLET.COIN_ID.eq(coinId))).fetchAny();
|
||||
if(walletRecord == null){
|
||||
walletRecord = dslContext.newRecord(T_MEMBER_WALLET);
|
||||
walletRecord.setCoinId(coinId);
|
||||
walletRecord.setMemberId(memberId);
|
||||
walletRecord.store();
|
||||
}
|
||||
return walletRecord;
|
||||
}
|
||||
|
||||
public boolean operateBalance(WalletOperation op) {
|
||||
return operateBalance(op.getWalletId(), op.getOpType(), op.getOpAmount(), op.getExtRemark());
|
||||
}
|
||||
|
||||
public boolean operateBalance(Integer walletId, WalletLogTypeEnum logType, BigDecimal opValue, String extRemark) {
|
||||
if (walletId == null) {
|
||||
return false;
|
||||
}
|
||||
if (opValue.compareTo(BigDecimal.ZERO) == 0) {
|
||||
return true;
|
||||
}
|
||||
int result = dslContext.update(T_MEMBER_WALLET)
|
||||
.set(T_MEMBER_WALLET.BALANCE, T_MEMBER_WALLET.BALANCE.add(opValue))
|
||||
.where(T_MEMBER_WALLET.ID.eq(walletId).and(T_MEMBER_WALLET.BALANCE.ge(opValue.negate())))
|
||||
.execute();
|
||||
if (result == 0) {
|
||||
return false;
|
||||
}
|
||||
TMemberWalletRecord walletRecord = getWallet(walletId);
|
||||
dslContext.insertInto(T_MEMBER_WALLET_LOG)
|
||||
.set(T_MEMBER_WALLET_LOG.WALLET_ID, walletId)
|
||||
.set(T_MEMBER_WALLET_LOG.MEMBER_ID, walletRecord.getMemberId())
|
||||
.set(T_MEMBER_WALLET_LOG.TYPE, 1)
|
||||
.set(T_MEMBER_WALLET_LOG.COIN_ID, walletRecord.getCoinId())
|
||||
.set(T_MEMBER_WALLET_LOG.OP_VALUE, opValue)
|
||||
.set(T_MEMBER_WALLET_LOG.OP_BEFORE, walletRecord.getBalance().subtract(opValue))
|
||||
.set(T_MEMBER_WALLET_LOG.OP_AFTER, walletRecord.getBalance())
|
||||
.set(T_MEMBER_WALLET_LOG.OP_TYPE, logType.getCode())
|
||||
.set(T_MEMBER_WALLET_LOG.OP_REMARK, logType.getRemark())
|
||||
.set(T_MEMBER_WALLET_LOG.EXT_REMARK, extRemark != null ? extRemark : "")
|
||||
.execute();
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean operateFrozen(WalletOperation op) {
|
||||
return operateFrozen(op.getWalletId(), op.getOpType(), op.getOpAmount(), op.getExtRemark());
|
||||
}
|
||||
|
||||
public boolean operateFrozen(Integer walletId, WalletLogTypeEnum logType, BigDecimal opValue, String extRemark) {
|
||||
if (walletId == null) {
|
||||
return false;
|
||||
}
|
||||
if (opValue.compareTo(BigDecimal.ZERO) == 0) {
|
||||
return true;
|
||||
}
|
||||
int result = dslContext.update(T_MEMBER_WALLET)
|
||||
.set(T_MEMBER_WALLET.FROZEN, T_MEMBER_WALLET.FROZEN.add(opValue))
|
||||
.where(T_MEMBER_WALLET.ID.eq(walletId).and(T_MEMBER_WALLET.FROZEN.ge(opValue.negate())))
|
||||
.execute();
|
||||
if (result == 0) {
|
||||
return false;
|
||||
}
|
||||
TMemberWalletRecord walletRecord = getWallet(walletId);
|
||||
dslContext.insertInto(T_MEMBER_WALLET_LOG)
|
||||
.set(T_MEMBER_WALLET_LOG.WALLET_ID, walletId)
|
||||
.set(T_MEMBER_WALLET_LOG.MEMBER_ID, walletRecord.getMemberId())
|
||||
.set(T_MEMBER_WALLET_LOG.TYPE, 2)
|
||||
.set(T_MEMBER_WALLET_LOG.COIN_ID, walletRecord.getCoinId())
|
||||
.set(T_MEMBER_WALLET_LOG.OP_VALUE, opValue)
|
||||
.set(T_MEMBER_WALLET_LOG.OP_BEFORE, walletRecord.getFrozen().subtract(opValue))
|
||||
.set(T_MEMBER_WALLET_LOG.OP_AFTER, walletRecord.getFrozen())
|
||||
.set(T_MEMBER_WALLET_LOG.OP_TYPE, logType.getCode())
|
||||
.set(T_MEMBER_WALLET_LOG.OP_REMARK, logType.getRemark())
|
||||
.set(T_MEMBER_WALLET_LOG.EXT_REMARK, extRemark != null ? extRemark : "")
|
||||
.execute();
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean batchOperate(List<WalletOperation> operations) {
|
||||
return batchOperate(operations, true);
|
||||
}
|
||||
|
||||
public boolean batchOperate(List<WalletOperation> operations, boolean check) {
|
||||
return batchOperate(operations, check, true);
|
||||
}
|
||||
|
||||
public boolean batchOperate(List<WalletOperation> operations, boolean check, boolean sort) {
|
||||
if (sort) {
|
||||
operations.sort(Comparator.comparingInt(WalletOperation::getWalletId));
|
||||
}
|
||||
for (WalletOperation item : operations) {
|
||||
boolean res = false;
|
||||
switch (item.getType()) {
|
||||
case 1:
|
||||
res = operateBalance(item);
|
||||
break;
|
||||
case 2:
|
||||
res = operateFrozen(item);
|
||||
break;
|
||||
default:
|
||||
log.warn("bad wallet operate type");
|
||||
}
|
||||
if (!res && check) {
|
||||
log.error("批量操作失败");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void verifyActivityStatisticsRecord(String account) {
|
||||
Integer count = dslContext.selectCount().from(ACTIVITY_STATISTICS).where(ACTIVITY_STATISTICS.ADDRESS.eq(account)).fetchAnyInto(Integer.class);
|
||||
if(count == null || count == 0){
|
||||
//实例化用户资产统计
|
||||
ActivityStatisticsRecord statisticsRecord = dslContext.newRecord(ACTIVITY_STATISTICS);
|
||||
statisticsRecord.setAddress(account);
|
||||
statisticsRecord.setAmount(BigDecimal.ZERO);
|
||||
statisticsRecord.store();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
package com.alive.server.task;
|
||||
|
||||
import com.alive.server.service.TaskService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.annotation.Isolation;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
|
||||
/**
|
||||
* 活动定时任务
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
@Transactional(isolation = Isolation.READ_COMMITTED)
|
||||
public class ActivityTask {
|
||||
|
||||
@Autowired
|
||||
private TaskService taskService;
|
||||
|
||||
/**
|
||||
* 5分钟执行一次 关注、改名
|
||||
*/
|
||||
/*@Scheduled(initialDelay = 20_000, fixedDelay = 600_00 * 2)
|
||||
public void twitterOptimismExec() {
|
||||
taskService.optimismExec();
|
||||
}*/
|
||||
|
||||
/**
|
||||
* 5分钟执行一次 转载、点赞
|
||||
*/
|
||||
/*@Scheduled(initialDelay = 20_000, fixedDelay = 600_00 * 2)
|
||||
public void twitterActiveExec() {
|
||||
taskService.activeExec();
|
||||
}*/
|
||||
|
||||
/**
|
||||
* 5分钟执行一次 加入Discord
|
||||
*/
|
||||
/*@Scheduled(initialDelay = 20_000, fixedDelay = 600_00 * 2)
|
||||
public void addDiscord() {
|
||||
taskService.addDiscord();
|
||||
}*/
|
||||
|
||||
/**
|
||||
* 5分钟执行一次 加入TG
|
||||
*/
|
||||
/*@Scheduled(initialDelay = 20_000, fixedDelay = 600_00 * 2)
|
||||
public void addTg() {
|
||||
taskService.addTg();
|
||||
}*/
|
||||
|
||||
/**
|
||||
* 10分钟执行一次 乐观验证任务
|
||||
*/
|
||||
/*@Scheduled(initialDelay = 20_000, fixedDelay = 600_00 * 2)
|
||||
public void optimisticValidation() {
|
||||
taskService.optimisticValidation();
|
||||
}*/
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
package com.alive.server.task;
|
||||
|
||||
import com.alive.server.service.CrowdfundingService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.annotation.Isolation;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 众筹
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
/*@Profile({"dev"})*/
|
||||
@Transactional(isolation = Isolation.READ_COMMITTED)
|
||||
public class CrowdfundingTask {
|
||||
|
||||
@Autowired
|
||||
private CrowdfundingService crowdfundingService;
|
||||
|
||||
/**
|
||||
* 节点交易确认 10分钟执行一次
|
||||
*/
|
||||
@Scheduled(initialDelay = 15_000, fixedDelay = 1000 * 60 * 10)
|
||||
public void exec() {
|
||||
crowdfundingService.exec();
|
||||
}
|
||||
|
||||
/**
|
||||
* 众筹监听
|
||||
* socket监听区块,socket同步日志,监听最新的数据
|
||||
* 10分钟重启一次,防止异常停止监听
|
||||
* @throws InterruptedException
|
||||
*/
|
||||
@Scheduled(initialDelay = 15 * 1000, fixedDelay = 10 * 1000)
|
||||
public void bscScanTaskWithWs(){
|
||||
crowdfundingService.bscScanTask();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
package com.alive.server.task;
|
||||
|
||||
import com.alive.server.service.OnChainTransfersService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
|
||||
/**
|
||||
* 活动定时任务 链上转账
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
public class TransferTask {
|
||||
|
||||
@Autowired
|
||||
private OnChainTransfersService onChainTransfersService;
|
||||
|
||||
/**
|
||||
* 5分钟执行一次 链上转账
|
||||
*/
|
||||
@Scheduled(initialDelay = 20_000, fixedDelay = 600_00 * 2)
|
||||
public void exec() {
|
||||
//onChainTransfersService.transfer();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
package com.alive.server.task;
|
||||
|
||||
import com.alive.server.service.BscTimingService;
|
||||
import com.alive.server.service.BtcBuyService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
|
||||
/**
|
||||
* @author HayDen
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
public class WsBscScanTask {
|
||||
|
||||
@Autowired
|
||||
private BscTimingService bscScanTask;
|
||||
|
||||
@Autowired
|
||||
private BtcBuyService btcBuyService;
|
||||
|
||||
/**
|
||||
* 节点交易确认 10分钟执行一次
|
||||
*/
|
||||
@Scheduled(initialDelay = 15_000, fixedDelay = 1000 * 60 * 10)
|
||||
public void btcTransactionConfirmation() {
|
||||
//btcBuyService.exec();
|
||||
}
|
||||
|
||||
/**
|
||||
* socket监听区块,socket同步日志,监听最新的数据
|
||||
* 10分钟重启一次,防止异常停止监听
|
||||
* @throws InterruptedException
|
||||
*/
|
||||
@Scheduled(initialDelay = 15 * 1000, fixedDelay = 6 * 1000)
|
||||
public void bscScanTaskWithWs(){
|
||||
//bscScanTask.bscScanTask();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
package com.alive.server.task;
|
||||
|
||||
import com.alive.server.service.BscWsService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.web3j.protocol.Web3j;
|
||||
import org.web3j.protocol.http.HttpService;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
* @author HayDen
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
public class WsCrossBridgesScanTask {
|
||||
|
||||
/**
|
||||
* socket节点
|
||||
*/
|
||||
@Value("${com.alive.roosChainWsUrl}")
|
||||
private String roosChainWsUrl;
|
||||
|
||||
/**
|
||||
* 合约地址
|
||||
*/
|
||||
@Value("${com.alive.roosContractUrl}")
|
||||
private String roosContractUrl;
|
||||
|
||||
@Autowired
|
||||
private BscWsService bscWsService;
|
||||
|
||||
public Web3j getCrossBridgesBscWsWeb3j() {
|
||||
return Web3j.build(new HttpService(roosChainWsUrl));
|
||||
}
|
||||
|
||||
/**
|
||||
* 需要同步日志的合约
|
||||
* @return
|
||||
*/
|
||||
private List<String> getAddresses() {
|
||||
return Arrays.asList(roosContractUrl);
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证跨连桥任务数据
|
||||
* 10分钟重启一次,防止异常停止监听
|
||||
* @throws InterruptedException
|
||||
*/
|
||||
@Scheduled(initialDelay = 15 * 1000, fixedDelay = 60 * 1000 * 10)
|
||||
public void crossBridgesBscScanTaskWithWs(){
|
||||
/* long threadId = Thread.currentThread().getId();
|
||||
log.info("enter {}", threadId);
|
||||
EthFilter filter = new EthFilter(
|
||||
DefaultBlockParameter.valueOf("latest"),
|
||||
DefaultBlockParameter.valueOf("latest"),
|
||||
this.getAddresses()
|
||||
);
|
||||
Flowable<Log> flowable = this.getCrossBridgesBscWsWeb3j().ethLogFlowable(filter);
|
||||
bscWsService.wsExec(flowable);*/
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
package com.alive.server.web3;
|
||||
|
||||
import org.web3j.protocol.core.methods.response.EthLog;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface ContractEventHandle {
|
||||
|
||||
String handle(EthLog.LogObject logObject, List<String> dataList);
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
package com.alive.server.web3;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.KeyGenerator;
|
||||
import javax.crypto.SecretKey;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Objects;
|
||||
|
||||
public class RLPEncryption {
|
||||
|
||||
private static final String AES_ALGORITHM = "AES";
|
||||
|
||||
public static byte[] encrypt(byte[] key, byte[] data) throws Exception {
|
||||
SecretKeySpec secretKeySpec = new SecretKeySpec(key, AES_ALGORITHM);
|
||||
Cipher cipher = Cipher.getInstance(AES_ALGORITHM);
|
||||
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
|
||||
return cipher.doFinal(data);
|
||||
}
|
||||
|
||||
public static byte[] decrypt(byte[] key, byte[] encryptedData) throws Exception {
|
||||
SecretKeySpec secretKeySpec = new SecretKeySpec(key, AES_ALGORITHM);
|
||||
Cipher cipher = Cipher.getInstance(AES_ALGORITHM);
|
||||
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec);
|
||||
return cipher.doFinal(encryptedData);
|
||||
}
|
||||
|
||||
public static SecretKey generateAESKey(int keySize) throws NoSuchAlgorithmException {
|
||||
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
|
||||
keyGenerator.init(keySize);
|
||||
return keyGenerator.generateKey();
|
||||
}
|
||||
|
||||
public static String bytesToHex(byte[] bytes) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (byte b : bytes) {
|
||||
sb.append(String.format("%02X", b));
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
package com.alive.server.web3;
|
||||
|
||||
import java.security.*;
|
||||
import javax.crypto.Cipher;
|
||||
|
||||
public class RSAEncryption {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
// 要加密的明文
|
||||
String plainText = "Hello, World!";
|
||||
|
||||
// 1. 生成 RSA 密钥对
|
||||
KeyPair keyPair = generateRSAKeyPair();
|
||||
PublicKey publicKey = keyPair.getPublic();
|
||||
|
||||
// 2. 使用 Solidity 合约提供的公钥加密数据
|
||||
byte[] encryptedData = encryptData(publicKey, plainText.getBytes());
|
||||
System.out.println("Encrypted data: " + new String(encryptedData));
|
||||
|
||||
// 将加密后的数据发送到 Solidity 合约
|
||||
}
|
||||
|
||||
public static KeyPair generateRSAKeyPair() throws Exception {
|
||||
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
|
||||
keyPairGenerator.initialize(2048);
|
||||
return keyPairGenerator.generateKeyPair();
|
||||
}
|
||||
|
||||
public static byte[] encryptData(PublicKey publicKey, byte[] data) throws Exception {
|
||||
Cipher cipher = Cipher.getInstance("RSA");
|
||||
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
|
||||
return cipher.doFinal(data);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,193 @@
|
|||
package com.alive.server.web3;
|
||||
|
||||
import com.alive.db.entity.Vo.PayCoinVo;
|
||||
import com.alive.db.entity.Vo.TransactionDataVo;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.web3j.protocol.Web3j;
|
||||
import org.web3j.protocol.core.methods.response.EthGetTransactionReceipt;
|
||||
import org.web3j.protocol.core.methods.response.Log;
|
||||
import org.web3j.protocol.core.methods.response.TransactionReceipt;
|
||||
import org.web3j.protocol.http.HttpService;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
public class Web3jServer {
|
||||
|
||||
/**
|
||||
* 普通节点
|
||||
*/
|
||||
@Value("${com.alive.chainUrl}")
|
||||
private String chainUrl;
|
||||
|
||||
|
||||
public Web3j getWeb3j(){
|
||||
return Web3j.build(new HttpService(chainUrl));
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过hash获取交易的数据
|
||||
* @param hash
|
||||
* @return
|
||||
*/
|
||||
public TransactionDataVo getEthLogsByHash(String hash) throws IOException {
|
||||
TransactionDataVo vo = new TransactionDataVo();
|
||||
EthGetTransactionReceipt transaction = this.getWeb3j().ethGetTransactionReceipt(hash).send();
|
||||
TransactionReceipt transactionReceipt = transaction.getResult();
|
||||
if(transactionReceipt == null){
|
||||
return new TransactionDataVo().setStatus(-1);
|
||||
}
|
||||
//0=失败 1=成功
|
||||
String status = typeCast16By10(transactionReceipt.getStatus());
|
||||
vo.setStatus(Integer.parseInt(status));
|
||||
if(!status.equals("1")){
|
||||
return vo;
|
||||
}
|
||||
vo.setFrom(transactionReceipt.getFrom().toLowerCase());
|
||||
List<Log> log = transactionReceipt.getLogs();
|
||||
if(log == null || log.size() == 0){
|
||||
return null;
|
||||
}
|
||||
//交易数据
|
||||
Log payLogs = log.get(0);
|
||||
vo.setPayAmount(new BigDecimal(typeCast16By10(payLogs.getData())));
|
||||
vo.setNftNumber(0);
|
||||
vo.setNftIds(new ArrayList<>());
|
||||
Integer lenth = log.size();
|
||||
for (int i = 0; i < lenth; i++) {
|
||||
List<String> topics = log.get(i).getTopics();
|
||||
if(topics.size() != 4 && vo.getNftIds().size() > 0){
|
||||
break;
|
||||
}
|
||||
if(topics.size() == 4){
|
||||
vo.setNftNumber(vo.getNftNumber() + 1);
|
||||
vo.getNftIds().add(Integer.parseInt(typeCast16By10(topics.get(3))));
|
||||
}
|
||||
}
|
||||
//取出上级地址
|
||||
payLogs = log.get(lenth - 2);
|
||||
if(payLogs.getTopics().size() != 3){
|
||||
payLogs = log.get(lenth - 3);
|
||||
}
|
||||
if(payLogs.getTopics().size() != 3){
|
||||
//没有上级
|
||||
vo.setTeamAmount(BigDecimal.ZERO);
|
||||
vo.setTeamAddress("0");
|
||||
}else{
|
||||
BigDecimal teamAmount = new BigDecimal(typeCast16By10(payLogs.getData()));
|
||||
vo.setTeamAmount(teamAmount);
|
||||
vo.setTeamAddress("0x"+payLogs.getTopics().get(2).substring(26,payLogs.getTopics().get(2).length()));
|
||||
}
|
||||
return vo;
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过hash获取交易的数据
|
||||
* @param hash
|
||||
* @return
|
||||
*/
|
||||
public PayCoinVo crowdfundingByHash(String hash) throws IOException {
|
||||
PayCoinVo vo = new PayCoinVo();
|
||||
vo.setUsdtAmount(BigDecimal.ZERO);
|
||||
EthGetTransactionReceipt transaction = this.getWeb3j().ethGetTransactionReceipt(hash).send();
|
||||
TransactionReceipt transactionReceipt = transaction.getResult();
|
||||
if(transactionReceipt == null){
|
||||
return new PayCoinVo().setStatus(-1);
|
||||
}
|
||||
//0=失败 1=成功
|
||||
String status = typeCast16By10(transactionReceipt.getStatus());
|
||||
vo.setStatus(Integer.parseInt(status));
|
||||
if(!status.equals("1")){
|
||||
return vo;
|
||||
}
|
||||
vo.setAddress(transactionReceipt.getFrom().toLowerCase());
|
||||
List<Log> log = transactionReceipt.getLogs();
|
||||
if(log == null || log.size() == 0){
|
||||
return null;
|
||||
}
|
||||
//交易数据
|
||||
Log payLogs = log.get(0);
|
||||
vo.setUsdtAmount(new BigDecimal(typeCast16By10(payLogs.getData())));
|
||||
payLogs = log.get(1);
|
||||
Integer len = payLogs.getData().length();
|
||||
vo.setOrderNumber(getValue(payLogs.getData().substring(len-64,len),0,false));
|
||||
return vo;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询日志里面加indexed的内容
|
||||
* @param value 转换的内容
|
||||
* @return 16进制转换成10进制
|
||||
*/
|
||||
public static String typeCast16By10(String value){
|
||||
String ret = value.substring(2,value.length());
|
||||
if(StringUtils.isBlank(ret)){
|
||||
return "0";
|
||||
}
|
||||
//16进制转10进制
|
||||
return new BigInteger(ret, 16).toString();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 将ETH地址转换成uint160
|
||||
* @param ethAddress
|
||||
* @return
|
||||
*/
|
||||
public static BigInteger addressToUint160(String ethAddress){
|
||||
// 将地址转换为 BigInteger
|
||||
BigInteger addressAsBigInt = new BigInteger(ethAddress.substring(2), 16);
|
||||
// Solidity 中的 uint160 最大值
|
||||
BigInteger uint160MaxValue = new BigInteger("ffffffffffffffffffffffffffffffffffffffff", 16);
|
||||
// 取地址的低 160 位作为 Solidity 中的 uint160
|
||||
BigInteger uint160Address = addressAsBigInt.and(uint160MaxValue);
|
||||
return uint160Address;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询日志里面加indexed的内容
|
||||
* @param topList 日志内容
|
||||
* @param code 查询第几个
|
||||
* @return
|
||||
*/
|
||||
public static BigInteger getNmber(List<String> topList, Integer code){
|
||||
String ret = topList.get(code);
|
||||
ret = ret.substring(2,ret.length());
|
||||
//16进制转10进制
|
||||
return new BigInteger(ret, 16);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取没有加indexed的内容
|
||||
* @param date 拆分的参数
|
||||
* @param code 取的位数
|
||||
* @param address 是否返回地址
|
||||
* @return
|
||||
*/
|
||||
public static String getValue(String date, Integer code, Boolean address){
|
||||
int number = 64;
|
||||
if(code == 0){
|
||||
date = date.substring(0,number);
|
||||
}else{
|
||||
code = number * code;
|
||||
date = date.substring(code,code+number);
|
||||
}
|
||||
if(address){
|
||||
return "0x"+date.substring(24,date.length());
|
||||
}else{
|
||||
return new BigInteger(date, 16).toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
spring:
|
||||
datasource:
|
||||
driver-class-name: com.mysql.cj.jdbc.Driver
|
||||
url: jdbc:mysql://127.0.0.1:3306/alive_dev?useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8&allowMultiQueries=true
|
||||
username: root
|
||||
password: root
|
||||
|
||||
redis:
|
||||
host: 127.0.0.1
|
||||
database: 2
|
||||
password:
|
||||
lettuce:
|
||||
pool:
|
||||
max-active: 20
|
||||
max-idle: 16
|
||||
max-wait: 1000ms
|
||||
min-idle: 10
|
||||
|
||||
com.alive:
|
||||
#ARB节点服务器
|
||||
chainUrl: 'https://go.getblock.io/7a508279a1a84ba6832cbc53f27e571a/'
|
||||
#ARBsocket节点服务器
|
||||
chainWsUrl: 'https://go.getblock.io/7a508279a1a84ba6832cbc53f27e571a/'
|
||||
contractUrl: '0x9B20e2e0b114D50B3a8328e7Ca8C1303aFDC13A4'
|
||||
|
||||
|
||||
#任务测试跨连桥合约监听器
|
||||
roosChainWsUrl: 'https://go.getblock.io/8181dc29e53a4ea4948e30c61e3e0aeb/'
|
||||
roosContractUrl: '0xeeEC77da95C788b58595Fcd7eBad1d87Ae821aCE'
|
||||
common:
|
||||
auth:
|
||||
jwtSecret: 'inode-dev'
|
||||
task:
|
||||
enable: true
|
||||
bot: true
|
||||
cron:
|
||||
sampleCronTask: '0 */10 * * * ?' # 示例cron任务
|
||||
|
||||
#链上转账配置
|
||||
chain:
|
||||
transfer:
|
||||
rpcUrl: 'https://testrpc.roospro.com'
|
||||
erc20: '0x204074AD198E7c6e79E195DAf576bc7D53967B45'
|
||||
privateKey: 'd94f3dc1629be0bb718ad9bb55d09d57de1667258101565f58d99018bdfba029'
|
|
@ -0,0 +1,44 @@
|
|||
spring:
|
||||
datasource:
|
||||
driver-class-name: com.mysql.cj.jdbc.Driver
|
||||
url: jdbc:mysql://127.0.0.1:3306/alive_prod?useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8&allowMultiQueries=true
|
||||
username: alive_prod
|
||||
password: 6jD2S3CGwGYhRXNp
|
||||
|
||||
redis:
|
||||
host: 127.0.0.1
|
||||
database: 7
|
||||
password:
|
||||
lettuce:
|
||||
pool:
|
||||
max-active: 20
|
||||
max-idle: 16
|
||||
max-wait: 1000ms
|
||||
min-idle: 10
|
||||
|
||||
com.alive:
|
||||
#ARB节点服务器
|
||||
chainUrl: 'https://go.getblock.io/e3842ff6182b4907ac9863503e77744e/'
|
||||
#ARBsocket节点服务器
|
||||
chainWsUrl: 'https://go.getblock.io/e3842ff6182b4907ac9863503e77744e/'
|
||||
contractUrl: '0x92B64f3BCf327ada976Fa876c7F17b177f333Eea'
|
||||
|
||||
|
||||
#任务测试跨连桥合约监听器 暂时没有用到
|
||||
roosChainWsUrl: 'https://go.getblock.io/8181dc29e53a4ea4948e30c61e3e0aeb/'
|
||||
roosContractUrl: '0xeeEC77da95C788b58595Fcd7eBad1d87Ae821aCE'
|
||||
common:
|
||||
auth:
|
||||
jwtSecret: 'inode-dev'
|
||||
task:
|
||||
enable: true
|
||||
bot: true
|
||||
cron:
|
||||
sampleCronTask: '0 */10 * * * ?' # 示例cron任务
|
||||
|
||||
#链上转账配置
|
||||
chain:
|
||||
transfer:
|
||||
rpcUrl: 'https://testrpc.roospro.com'
|
||||
erc20: '0x204074AD198E7c6e79E195DAf576bc7D53967B45'
|
||||
privateKey: 'd94f3dc1629be0bb718ad9bb55d09d57de1667258101565f58d99018bdfba029'
|
|
@ -0,0 +1,44 @@
|
|||
spring:
|
||||
datasource:
|
||||
driver-class-name: com.mysql.cj.jdbc.Driver
|
||||
url: jdbc:mysql://127.0.0.1:3306/alive_test?useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8&allowMultiQueries=true
|
||||
username: alive_test
|
||||
password: cf2xrRTPHL875NRA
|
||||
|
||||
redis:
|
||||
host: 127.0.0.1
|
||||
database: 2
|
||||
password:
|
||||
lettuce:
|
||||
pool:
|
||||
max-active: 20
|
||||
max-idle: 16
|
||||
max-wait: 1000ms
|
||||
min-idle: 10
|
||||
|
||||
com.alive:
|
||||
#ARB节点服务器
|
||||
chainUrl: 'https://go.getblock.io/7a508279a1a84ba6832cbc53f27e571a/'
|
||||
#ARBsocket节点服务器
|
||||
chainWsUrl: 'https://go.getblock.io/7a508279a1a84ba6832cbc53f27e571a/'
|
||||
contractUrl: '0x9B20e2e0b114D50B3a8328e7Ca8C1303aFDC13A4'
|
||||
|
||||
|
||||
#任务测试跨连桥合约监听器
|
||||
roosChainWsUrl: 'https://go.getblock.io/8181dc29e53a4ea4948e30c61e3e0aeb/'
|
||||
roosContractUrl: '0xeeEC77da95C788b58595Fcd7eBad1d87Ae821aCE'
|
||||
common:
|
||||
auth:
|
||||
jwtSecret: 'inode-dev'
|
||||
task:
|
||||
enable: true
|
||||
bot: true
|
||||
cron:
|
||||
sampleCronTask: '0 */10 * * * ?' # 示例cron任务
|
||||
|
||||
#链上转账配置
|
||||
chain:
|
||||
transfer:
|
||||
rpcUrl: 'https://testrpc.roospro.com'
|
||||
erc20: '0x204074AD198E7c6e79E195DAf576bc7D53967B45'
|
||||
privateKey: 'd94f3dc1629be0bb718ad9bb55d09d57de1667258101565f58d99018bdfba029'
|
|
@ -0,0 +1,45 @@
|
|||
server:
|
||||
port: 8181
|
||||
shutdown: graceful
|
||||
servlet:
|
||||
encoding:
|
||||
force: true
|
||||
charset: UTF-8
|
||||
|
||||
spring:
|
||||
profiles:
|
||||
active: prod
|
||||
application:
|
||||
name: inode-api
|
||||
jackson:
|
||||
serialization: # 返回时间戳
|
||||
write-dates-as-timestamps: true
|
||||
servlet:
|
||||
multipart:
|
||||
max-file-size: 50MB
|
||||
max-request-size: 50MB
|
||||
|
||||
logging:
|
||||
level:
|
||||
root: warn
|
||||
com.alive: info
|
||||
|
||||
com.alive:
|
||||
upload:
|
||||
filePath: '/data/upload'
|
||||
defaultUrlPreFix: 'http://file.alive.com/upload/'
|
||||
|
||||
config:
|
||||
tokenHeader: 'Authorization'
|
||||
tokenRedisKeyFormat: 'smt:token:%d:%s'
|
||||
tokenExpireSeconds: 25920000
|
||||
limitLoginOneOnly: false
|
||||
|
||||
file-provider:
|
||||
ribbon:
|
||||
listOfServers: http://adjjw.jiujiwang.com.cn/
|
||||
ConnectTimeout: 6000
|
||||
ReadTimeout: 6000
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
ResultCodeEnum.0 = Request Successful
|
||||
ResultCodeEnum.400 = Request Failed
|
||||
ResultCodeEnum.401 = Login Required
|
||||
ResultCodeEnum.402 = Access Denied
|
||||
ResultCodeEnum.500 = Network Exception
|
||||
|
||||
WalletLogTypeEnum.0 = System Operation
|
||||
WalletLogTypeEnum.1 = System Recharge
|
||||
WalletLogTypeEnum.2 = System Deduction
|
||||
WalletLogTypeEnum.3 = Registration Gift
|
||||
WalletLogTypeEnum.4 = Withdrawal
|
||||
WalletLogTypeEnum.5 = Withdrawal Fee
|
||||
WalletLogTypeEnum.6 = Withdrawal Rejected
|
||||
WalletLogTypeEnum.7 = Transferred to {0}
|
||||
WalletLogTypeEnum.8 = Transferred from {0}
|
||||
WalletLogTypeEnum.9 = Exchanged Out
|
||||
WalletLogTypeEnum.10 = Exchanged In
|
||||
WalletLogTypeEnum.11 = Purchase Goods
|
||||
WalletLogTypeEnum.12 = Shopping Gift
|
||||
WalletLogTypeEnum.13 = Shopping Reward
|
||||
WalletLogTypeEnum.14 = Sign In
|
||||
WalletLogTypeEnum.15 = Sign In Reward
|
||||
WalletLogTypeEnum.16 = Daily Release
|
||||
WalletLogTypeEnum.17 = Team Reward
|
||||
WalletLogTypeEnum.18 = Cancel Order
|
||||
WalletLogTypeEnum.19 = Lucky Draw
|
||||
WalletLogTypeEnum.20 = Accelerated Release
|
||||
WalletLogTypeEnum.21 = Transfer Out
|
||||
WalletLogTypeEnum.22 = Transfer In
|
||||
WalletLogTypeEnum.23 = Static Release
|
||||
WalletLogTypeEnum.24 = Accelerated Release
|
||||
WalletLogTypeEnum.25 = Reservation of Equity Token
|
||||
WalletLogTypeEnum.26 = Pre-purchase Success
|
||||
WalletLogTypeEnum.27 = Pre-purchase Refund
|
||||
WalletLogTypeEnum.28 = Participate in Sale
|
||||
WalletLogTypeEnum.29 = Startup Investment Thaw
|
|
@ -0,0 +1,211 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<groupId>com.alive</groupId>
|
||||
<artifactId>alive-api-server</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>alive-commons</artifactId>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-redis</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-cache</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.baomidou</groupId>
|
||||
<artifactId>mybatis-plus-boot-starter</artifactId>
|
||||
<version>3.3.2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-jdbc</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-jpa</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-jooq</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!--feign-->
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-feign</artifactId>
|
||||
<version>1.4.7.RELEASE</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
|
||||
<version>2.2.3.RELEASE</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.github.openfeign.form</groupId>
|
||||
<artifactId>feign-form</artifactId>
|
||||
<version>3.8.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.github.openfeign.form</groupId>
|
||||
<artifactId>feign-form-spring</artifactId>
|
||||
<version>3.8.0</version>
|
||||
</dependency>
|
||||
|
||||
<!--swagger-->
|
||||
<dependency>
|
||||
<groupId>io.springfox</groupId>
|
||||
<artifactId>springfox-swagger2</artifactId>
|
||||
<version>2.7.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.github.xiaoymin</groupId>
|
||||
<artifactId>swagger-bootstrap-ui</artifactId>
|
||||
<version>1.9.6</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>commons-lang</groupId>
|
||||
<artifactId>commons-lang</artifactId>
|
||||
<version>2.6</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
<version>3.8.1</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>commons-codec</groupId>
|
||||
<artifactId>commons-codec</artifactId>
|
||||
<version>1.11</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-pool2</artifactId>
|
||||
<version>2.7.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>commons-beanutils</groupId>
|
||||
<artifactId>commons-beanutils</artifactId>
|
||||
<version>1.9.4</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.sun.mail</groupId>
|
||||
<artifactId>javax.mail</artifactId>
|
||||
<version>1.5.6</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-annotations</artifactId>
|
||||
<version>2.9.7</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
<artifactId>gson</artifactId>
|
||||
<version>2.8.5</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>fastjson</artifactId>
|
||||
<version>1.2.70</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.squareup.okhttp3</groupId>
|
||||
<artifactId>okhttp</artifactId>
|
||||
<version>3.8.1</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.squareup.okhttp3</groupId>
|
||||
<artifactId>logging-interceptor</artifactId>
|
||||
<version>3.8.1</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.12</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.web3j</groupId>
|
||||
<artifactId>core</artifactId>
|
||||
<version>3.4.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.hibernate</groupId>
|
||||
<artifactId>hibernate-validator</artifactId>
|
||||
<version>6.0.18.Final</version>
|
||||
</dependency>
|
||||
|
||||
<!-- excel -->
|
||||
<dependency>
|
||||
<groupId>org.apache.poi</groupId>
|
||||
<artifactId>poi</artifactId>
|
||||
<version>3.13</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.poi</groupId>
|
||||
<artifactId>poi-ooxml</artifactId>
|
||||
<version>3.13</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>joda-time</groupId>
|
||||
<artifactId>joda-time</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.auth0</groupId>
|
||||
<artifactId>java-jwt</artifactId>
|
||||
<version>3.3.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.aliyun</groupId>
|
||||
<artifactId>dysmsapi20170525</artifactId>
|
||||
<version>2.0.22</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
</project>
|
|
@ -0,0 +1,64 @@
|
|||
package com.alive.commons;
|
||||
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
@Lazy(false)
|
||||
public class SpringContextHolder implements ApplicationContextAware, DisposableBean {
|
||||
|
||||
private static ApplicationContext applicationContext = null;
|
||||
|
||||
|
||||
/**
|
||||
* 取得存储在静态变量中的ApplicationContext.
|
||||
*/
|
||||
public static ApplicationContext getApplicationContext() {
|
||||
return applicationContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* 从静态变量applicationContext中取得Bean, 自动转型为所赋值对象的类型.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> T getBean(String name) {
|
||||
return (T) applicationContext.getBean(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* 从静态变量applicationContext中取得Bean, 自动转型为所赋值对象的类型.
|
||||
*/
|
||||
public static <T> T getBean(Class<T> requiredType) {
|
||||
return applicationContext.getBean(requiredType);
|
||||
}
|
||||
|
||||
public static <T> T getBean(String name, Class<T> clazz) {
|
||||
return getApplicationContext().getBean(name, clazz);
|
||||
}
|
||||
|
||||
/**
|
||||
* 清除SpringContextHolder中的ApplicationContext为Null.
|
||||
*/
|
||||
public static void clearHolder() {
|
||||
applicationContext = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 实现ApplicationContextAware接口, 注入Context到静态变量中.
|
||||
*/
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext appContext) {
|
||||
applicationContext = appContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* 实现DisposableBean接口, 在Context关闭时清理静态变量.
|
||||
*/
|
||||
@Override
|
||||
public void destroy() {
|
||||
SpringContextHolder.clearHolder();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
package com.alive.commons.annotation;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
@Inherited
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ElementType.METHOD})
|
||||
public @interface BusinessLog {
|
||||
/**
|
||||
* 业务的名称,例如:"修改菜单"
|
||||
*/
|
||||
String value() default "";
|
||||
|
||||
boolean skipLogParam() default false;
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
package com.alive.commons.annotation;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
@Target({ElementType.METHOD, ElementType.TYPE})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
public @interface Login {
|
||||
|
||||
//该接口是否加密
|
||||
boolean encrypted() default false;
|
||||
|
||||
//AES解密密钥,在encrypted为true时有效,若不指定,则从当前token中获取
|
||||
String key() default "";
|
||||
|
||||
//权限
|
||||
String[] permits() default {};
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue