新增文昌链作品存证;

六本木文昌链配置更新;
This commit is contained in:
yxz 2024-12-13 18:17:26 +08:00
parent f8b4ebe394
commit eb2aed5285
9 changed files with 188 additions and 25 deletions

View File

@ -4,6 +4,7 @@ import lombok.AllArgsConstructor;
import lombok.Builder; import lombok.Builder;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpHeaders; import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpRequest; import org.springframework.http.HttpRequest;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
@ -20,6 +21,7 @@ import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
@Component @Component
@Slf4j
public class LogClientHttpRequestInterceptor implements ClientHttpRequestInterceptor { public class LogClientHttpRequestInterceptor implements ClientHttpRequestInterceptor {
@Override @Override
public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException { public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
@ -46,7 +48,7 @@ public class LogClientHttpRequestInterceptor implements ClientHttpRequestInterce
RestLog restLog = RestLog.builder().costTime(stopWatch.getLastTaskTimeMillis()).headers(request.getHeaders()).method(request.getMethodValue()) RestLog restLog = RestLog.builder().costTime(stopWatch.getLastTaskTimeMillis()).headers(request.getHeaders()).method(request.getMethodValue())
.reqUrl(request.getURI().toString()).reqBody(new String(body, StandardCharsets.UTF_8)).resBody(resBody.toString()).resStatus(response.getRawStatusCode()).build(); .reqUrl(request.getURI().toString()).reqBody(new String(body, StandardCharsets.UTF_8)).resBody(resBody.toString()).resStatus(response.getRawStatusCode()).build();
System.out.println(restLog.toString()); log.info("请求信息:{}", restLog.toString());
return response; return response;
} }

View File

@ -0,0 +1,21 @@
package com.cpop.nftmeta.common.wenchang.model.req;
import lombok.Data;
/**
* @Version: 1.0
* @since: 2024/12/10
* @author: yxz
*/
@Data
public class WorkRecordReq {
private Integer identity_type;
private String identity_name;
private String identity_num;
private Integer type;
private String name;
private String description;
private String hash;
private Integer hash_type;
private String operation_id;
}

View File

@ -83,4 +83,14 @@ public interface AvataProxy {
* @return * @return
*/ */
NFTOperateDTO editNFT(EditNftReq editNftReq); NFTOperateDTO editNFT(EditNftReq editNftReq);
/**
* 作品存证
*
* @param workRecordReq
* @return
* @author yxz
* @since 2024/12/10
*/
NFTOperateDTO workRecord(WorkRecordReq workRecordReq) throws IllegalAccessException;
} }

View File

@ -18,6 +18,7 @@ import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder; import org.springframework.web.util.UriComponentsBuilder;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.lang.reflect.Field;
import java.net.URI; import java.net.URI;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
@ -45,6 +46,8 @@ public class AvataProxyImpl implements AvataProxy {
private static final String NFT_DESTORY_URL_PRE = "/v1beta1/nft/nfts/"; private static final String NFT_DESTORY_URL_PRE = "/v1beta1/nft/nfts/";
private static final String NFT_QUERY_URL = "/v1beta1/nft/nfts"; private static final String NFT_QUERY_URL = "/v1beta1/nft/nfts";
private static final String NFT_QUERY_DETAILS_URL = "/v1beta1/nft/nfts/"; private static final String NFT_QUERY_DETAILS_URL = "/v1beta1/nft/nfts/";
private static final String RECORDS_URL = "/v1beta1/record/records";
@Override @Override
public CreateAccountDTO createAccount(String name, String operationId) { public CreateAccountDTO createAccount(String name, String operationId) {
if (StringUtils.isBlank(name)) { if (StringUtils.isBlank(name)) {
@ -141,6 +144,52 @@ public class AvataProxyImpl implements AvataProxy {
} }
} }
/**
* 数字作品存证
*
* @param workRecordReq 工作记录要求
* @return {@link NFTOperateDTO }
* @author yxz
* @since 2024/12/10
*/
@Override
public NFTOperateDTO workRecord(WorkRecordReq workRecordReq) throws IllegalAccessException {
Map<String, Object> map = new HashMap<>();
Class<?> clazz = workRecordReq.getClass();
for (Field field : clazz.getDeclaredFields()) {
field.setAccessible(true);
map.put(field.getName(), field.get(workRecordReq));
}
Long currentTime = System.currentTimeMillis();
// 验签
String signature = AvataUtils.signRequest(RECORDS_URL, null, map, currentTime, wenchangConfig.getApiSecret());
// 请求体
HttpHeaders headers = getHttpHeader(signature, currentTime);
headers.setContentType(MediaType.parseMediaType("application/json"));
HttpEntity<String> httpEntity = new HttpEntity<>(new Gson().toJson(map), headers);
String url = wenchangConfig.getBaseUrl() + RECORDS_URL;
try {
// 接口调用
ParameterizedTypeReference<Message<NFTOperateDTO>> typeReference = new ParameterizedTypeReference<Message<NFTOperateDTO>>() {
};
ResponseEntity<Message<NFTOperateDTO>> responseEntity = restTemplate.exchange(url, HttpMethod.POST, httpEntity, typeReference);
Message<NFTOperateDTO> message = responseEntity.getBody();
assert message != null;
NFTOperateDTO nftOperateDTO = message.getData();
// 成功
log.info("创建数字作品存证成功:" + nftOperateDTO);
return nftOperateDTO;
} catch (Exception e) {
// 非200都会抛异常
// 处理异常
log.error("非200创建数字作品存证失败:参数为:" + workRecordReq);
e.printStackTrace();
throw new RuntimeException("创建数字作品存证失败");
}
}
@Override @Override
public NFTClassListDTO queryNFTClassList(NFTClassListReq nftClassListReq) { public NFTClassListDTO queryNFTClassList(NFTClassListReq nftClassListReq) {

View File

@ -131,4 +131,16 @@ public class CommonTask {
redisHashManager.deleteKey(RedisKey.USER_COUNTS_API_CHATGPT.getKey()); redisHashManager.deleteKey(RedisKey.USER_COUNTS_API_CHATGPT.getKey());
redisHashManager.deleteKey(RedisKey.USER_COUNTS_API_MIDJOURNEY.getKey()); redisHashManager.deleteKey(RedisKey.USER_COUNTS_API_MIDJOURNEY.getKey());
} }
/**
* 更新过期门票状态
*
* @author yxz
* @since 2024/12/02
*/
@Scheduled(cron = "0 1 0 * * ?")
public void executeExpiredTicket() {
log.info("=========== 更新过期门票状态 ===========");
// TODO 查找所有演出时间超过当前时间一天且未核销的门票并更新其状态为已过期
}
} }

View File

@ -50,16 +50,28 @@ spring:
min-idle: 5 min-idle: 5
youzan: youzan:
shop-id: 110316359 shop-id: 110316359
# 正式链 ## 正式链
#nft:
# wenchang:
# base-url: https://apis.avata.bianjie.ai
# chain-id: wenchangchain
# api-key: i2Y2K1o131v5o180O1D8C0L7t9a1P6Vo
# api-secret: j2g2G1u191G5N190R1y8F0h779U1O6qB
# default-class-id: avata888575453de22109e3e97da67e3fe1380fbc41df3fdb3344564bacd2972fca4f
# default-owner: iaa1m7a6dwlydrc0kautfhu7m2ncjgne5n5d0rc8dj
# project-id: 7UkrOsYJEbCd53Kl
# 六本木链
nft: nft:
wenchang: wenchang:
base-url: https://apis.avata.bianjie.ai base-url: https://apis.avata.bianjie.ai
chain-id: wenchangchain chain-id: wenchang-tianzhou
api-key: i2Y2K1o131v5o180O1D8C0L7t9a1P6Vo api-key: e2V4A0t8h2i790Q3y4x2T2k3L63764fw
api-secret: j2g2G1u191G5N190R1y8F0h779U1O6qB api-secret: x2j4Y0A8d2z730D3944232D3D6x7t4Q4
default-class-id: avata888575453de22109e3e97da67e3fe1380fbc41df3fdb3344564bacd2972fca4f default-class-id: avata888575453de22109e3e97da67e3fe1380fbc41df3fdb3344564bacd2972fca4f
default-owner: iaa1m7a6dwlydrc0kautfhu7m2ncjgne5n5d0rc8dj default-owner: iaa1pfctqdrl9cae6fk99g8kjn62fegme9zyj3kkr4
project-id: 7UkrOsYJEbCd53Kl project-id: 42y4b0x882Q770C3
# 测试链 # 测试链
#nft: #nft:
# wenchang: # wenchang:

View File

@ -17,6 +17,7 @@ import com.cpop.nftmeta.common.wenchang.model.dto.NFTDataDTO;
import com.cpop.nftmeta.common.wenchang.model.dto.NFTOperateDTO; import com.cpop.nftmeta.common.wenchang.model.dto.NFTOperateDTO;
import com.cpop.nftmeta.common.wenchang.model.req.NFTDestoryReq; import com.cpop.nftmeta.common.wenchang.model.req.NFTDestoryReq;
import com.cpop.nftmeta.common.wenchang.model.req.NFTPublishReq; import com.cpop.nftmeta.common.wenchang.model.req.NFTPublishReq;
import com.cpop.nftmeta.common.wenchang.model.req.WorkRecordReq;
import com.cpop.nftmeta.common.wenchang.proxy.AvataProxy; import com.cpop.nftmeta.common.wenchang.proxy.AvataProxy;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
@ -152,4 +153,39 @@ public class NFTTest {
memberNftMapper.updateById(memberNft); memberNftMapper.updateById(memberNft);
} }
} }
/**
* 数字作品存证
*
* @author yxz
* @since 2024/12/10
*/
@Test
public void wordRecord() throws IllegalAccessException {
WorkRecordReq workRecordReq = new WorkRecordReq();
workRecordReq.setIdentity_type(2);
workRecordReq.setIdentity_name("厦门六本木文化传媒有限公司");
workRecordReq.setIdentity_num("91350203MA31GKE04B");
workRecordReq.setType(1);
workRecordReq.setName("汕头超级音雄巨星演唱会门票-内场1080");
workRecordReq.setDescription("演唱会数字门票");
String hash = MD5.create().digestHex("https://uthmeta-1300336827.cos.ap-guangzhou.myqcloud.com/1733815941636.jpg");
workRecordReq.setHash(hash);
workRecordReq.setHash_type(3);
String operationId = UUID.fastUUID().toString(Boolean.FALSE);
log.info("operationId:{}", operationId);
workRecordReq.setOperation_id(operationId);
avataProxy.workRecord(workRecordReq);
}
/**
* 上链交易结果查询
*
* @author yxz
* @since 2024/12/10
*/
@Test
public void queryDealResult() {
avataProxy.queryDealResult("b9c10e3d-1f1b-4077-ac0c-8412e142cbc6");
}
} }

View File

@ -72,6 +72,17 @@ public class ZTicketFolderController {
// 门票数据 // 门票数据
BeanUtils.copyProperties(e, vo,"audienceName","idNumber"); BeanUtils.copyProperties(e, vo,"audienceName","idNumber");
if (e.getStatus() != 3){ if (e.getStatus() != 3){
String qrcode ;
// 票据二维码 用户id和票夹id
if (e.getAudienceName() == null || e.getIdNumber() == null){
qrcode = "请完善观演人信息";
}else {
String qrcodeString = userInfo.getUserId() + ":" + e.getFolderId();
String encrypt = aesUtils.encrypt(qrcodeString);
qrcode = "data:image/png;base64," + ImgUtil.toBase64(
QrCodeUtil.generate(encrypt, 128, 128),"png");
}
vo.setQrCode(qrcode);
// 演出数据 // 演出数据
ZShow show = zShowService.getById(e.getShowId()); ZShow show = zShowService.getById(e.getShowId());
BeanUtils.copyProperties(show, vo); BeanUtils.copyProperties(show, vo);
@ -85,12 +96,6 @@ public class ZTicketFolderController {
// 票档名称 // 票档名称
ZTicketTier tier = zTicketTierService.getById(e.getTicketTierId()); ZTicketTier tier = zTicketTierService.getById(e.getTicketTierId());
vo.setTierName(tier.getTierName()); vo.setTierName(tier.getTierName());
// 票据二维码 用户id和票夹id
String qrcodeString = userInfo.getUserId() + ":" + e.getFolderId();
String encrypt = aesUtils.encrypt(qrcodeString);
String qrcode = "data:image/png;base64," + ImgUtil.toBase64(
QrCodeUtil.generate(encrypt, 128, 128),"png");
vo.setQrCode(qrcode);
} }
return vo; return vo;
}).collect(Collectors.toList()); }).collect(Collectors.toList());
@ -108,6 +113,17 @@ public class ZTicketFolderController {
TicketFolderVO vo = new TicketFolderVO(); TicketFolderVO vo = new TicketFolderVO();
// 门票数据 // 门票数据
BeanUtils.copyProperties(e, vo,"audienceName","idNumber"); BeanUtils.copyProperties(e, vo,"audienceName","idNumber");
String qrcode ;
// 票据二维码 用户id和票夹id
if (e.getAudienceName() == null || e.getIdNumber() == null){
qrcode = "请完善观演人信息";
} else {
String qrcodeString = userInfo.getUserId() + ":" + e.getFolderId();
String encrypt = aesUtils.encrypt(qrcodeString);
qrcode = "data:image/png;base64," + ImgUtil.toBase64(
QrCodeUtil.generate(encrypt, 128, 128),"png");
}
vo.setQrCode(qrcode);
// 观演人信息 // 观演人信息
String audienceName = e.getAudienceName(); String audienceName = e.getAudienceName();
String newAudienceName = audienceName.substring(0, audienceName.length() - 1) + "*"; String newAudienceName = audienceName.substring(0, audienceName.length() - 1) + "*";
@ -121,12 +137,6 @@ public class ZTicketFolderController {
// 票档名称 // 票档名称
ZTicketTier tier = zTicketTierService.getById(e.getTicketTierId()); ZTicketTier tier = zTicketTierService.getById(e.getTicketTierId());
vo.setTierName(tier.getTierName()); vo.setTierName(tier.getTierName());
// 票据二维码 用户id和票夹id
String qrcodeString = userInfo.getUserId() + ":" + e.getFolderId();
String encrypt = aesUtils.encrypt(qrcodeString);
String qrcode = "data:image/png;base64," + ImgUtil.toBase64(
QrCodeUtil.generate(encrypt, 128, 128),"png");
vo.setQrCode(qrcode);
return vo; return vo;
}).collect(Collectors.toList()); }).collect(Collectors.toList());
} }

View File

@ -40,16 +40,27 @@ spring:
youzan: youzan:
shop-id: 110316359 shop-id: 110316359
# 生产链 # 数元链
#nft:
# wenchang:
# base-url: https://apis.avata.bianjie.ai
# chain-id: wenchangchain
# api-key: i2Y2K1o131v5o180O1D8C0L7t9a1P6Vo
# api-secret: j2g2G1u191G5N190R1y8F0h779U1O6qB
# default-class-id: avata888575453de22109e3e97da67e3fe1380fbc41df3fdb3344564bacd2972fca4f
# default-owner: iaa1m7a6dwlydrc0kautfhu7m2ncjgne5n5d0rc8dj
# project-id: 7UkrOsYJEbCd53Kl
# 六本木链
nft: nft:
wenchang: wenchang:
base-url: https://apis.avata.bianjie.ai base-url: https://apis.avata.bianjie.ai
chain-id: wenchangchain chain-id: wenchang-tianzhou
api-key: i2Y2K1o131v5o180O1D8C0L7t9a1P6Vo api-key: e2V4A0t8h2i790Q3y4x2T2k3L63764fw
api-secret: j2g2G1u191G5N190R1y8F0h779U1O6qB api-secret: x2j4Y0A8d2z730D3944232D3D6x7t4Q4
default-class-id: avata888575453de22109e3e97da67e3fe1380fbc41df3fdb3344564bacd2972fca4f default-class-id: avata888575453de22109e3e97da67e3fe1380fbc41df3fdb3344564bacd2972fca4f
default-owner: iaa1m7a6dwlydrc0kautfhu7m2ncjgne5n5d0rc8dj default-owner: iaa1pfctqdrl9cae6fk99g8kjn62fegme9zyj3kkr4
project-id: 7UkrOsYJEbCd53Kl project-id: 42y4b0x882Q770C3
# 测试链 # 测试链
#nft: #nft: