This commit is contained in:
gaojiuqi 2022-02-25 17:12:38 +08:00
parent 846e83f180
commit e5f05825de
40 changed files with 1317 additions and 138 deletions

12
pom.xml
View File

@ -8,12 +8,12 @@
<version>2.6.3</version> <version>2.6.3</version>
<relativePath/> <!-- lookup parent from repository --> <relativePath/> <!-- lookup parent from repository -->
</parent> </parent>
<groupId>com.szxgl.nft2022</groupId> <groupId>com.szxgl.nft</groupId>
<artifactId>pars-nft2022</artifactId> <artifactId>pars-nft</artifactId>
<version>0.0.1-SNAPSHOT</version> <version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging> <packaging>war</packaging>
<name>pars-nft2022</name> <name>pars-nft</name>
<description>pars-nft2022</description> <description>pars-nft</description>
<properties> <properties>
<java.version>1.8</java.version> <java.version>1.8</java.version>
<mybatisplus.version>3.4.2</mybatisplus.version> <mybatisplus.version>3.4.2</mybatisplus.version>
@ -111,6 +111,10 @@
<version>1.1.0</version> <version>1.1.0</version>
</dependency> </dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
</dependencies> </dependencies>

View File

@ -1,4 +1,4 @@
package com.szxgl.nft2022; package com.szxgl.nft;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;

View File

@ -0,0 +1,53 @@
package com.szxgl.nft.config;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import java.net.UnknownHostException;
@Configuration
@SuppressWarnings("all")
//镇压所有警告
public class RedisConfig {
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory)
throws UnknownHostException {
RedisTemplate<String, Object> template = new RedisTemplate<>();
// 默认的连接配置
template.setConnectionFactory(redisConnectionFactory);
// 序列化配置
// new 一个Jackson序列化对象用于后面的设置
Jackson2JsonRedisSerializer<Object> objectJackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
ObjectMapper objectMapper = new ObjectMapper();
// 用于转义
objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
objectJackson2JsonRedisSerializer.setObjectMapper(objectMapper);
// 创建string的序列化
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
// string的key和hash的key都采用string的序列化
// value都采用Jackson的序列化
//key采用string序列化方式
template.setKeySerializer(stringRedisSerializer);
//hash的key采用string序列化方式
template.setHashKeySerializer(stringRedisSerializer);
//value采用Jackson序列化方式
template.setValueSerializer(objectJackson2JsonRedisSerializer);
//hash的value采用Jackson序列化方式
template.setHashValueSerializer(objectJackson2JsonRedisSerializer);
return template;
}
}

View File

@ -1,20 +1,21 @@
package com.szxgl.nft2022.controller; package com.szxgl.nft.controller;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import com.szxgl.nft2022.entity.NftPhoto; import com.szxgl.nft.entity.UserNftPhoto;
import com.szxgl.nft2022.exception.ParameterException; import com.szxgl.nft.exception.ParameterException;
import com.szxgl.nft2022.service.NftPhotoService; import com.szxgl.nft.service.NftPhotoService;
import com.szxgl.nft2022.utils.EncryptUtil; import com.szxgl.nft.utils.*;
import com.szxgl.nft2022.utils.HttpClientUtil;
import com.szxgl.nft2022.utils.R;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@Controller import javax.servlet.http.HttpServletRequest;
import java.util.Map;
@RestController
@RequestMapping("/nft") @RequestMapping("/nft")
@Slf4j @Slf4j
public class NFTPhotoController { public class NFTPhotoController {
@ -32,11 +33,11 @@ public class NFTPhotoController {
if(StringUtils.isBlank(seed)){ if(StringUtils.isBlank(seed)){
log.error("seed不能为空"+seed); log.error("seed不能为空"+seed);
throw new ParameterException("seed不能为空"); return R.error("手机号不能为空");
} }
NftPhoto nftPhoto = nftPhotoService.getNftPhoto(seed); UserNftPhoto userNftPhoto = nftPhotoService.getNftPhoto(seed);
if(nftPhoto == null ){ if(userNftPhoto == null ){
//手机号加密 //手机号加密
String phone = encrypt(seed); String phone = encrypt(seed);
phone = String.format("{'phone':'%s'}",phone); phone = String.format("{'phone':'%s'}",phone);
@ -49,6 +50,13 @@ public class NFTPhotoController {
return R.ok(); return R.ok();
} }
/**
* 领取数字产品
* @param seed
* @param walletAddr
* @param paintingHash
* @return
*/
@PostMapping("/addNFTs") @PostMapping("/addNFTs")
public R addNFTs(String seed,String walletAddr,String paintingHash){ public R addNFTs(String seed,String walletAddr,String paintingHash){
if(StringUtils.isBlank(walletAddr)){ if(StringUtils.isBlank(walletAddr)){
@ -65,6 +73,33 @@ public class NFTPhotoController {
return R.ok(json); return R.ok(json);
} }
/**
* 领取数字产品展示页面
* @return
*/
@PostMapping("/getNftPhoto")
public R getNftPhoto(String openid,HttpServletRequest request){
// String openid = CookieUtil.getCookie(request.getCookies());
// if(StringUtils.isBlank(openid)){
// log.error("openid为空"+openid);
// throw new ParameterException("openid为空");
// }
Map<String, Object> map = nftPhotoService.getNftPhotoUrl(openid);
int status = (int)map.get("status");
String name = (String) map.get("name");
if(status == 1 ){
name = String.format("https://cdn.xglpa.com/pars-nft/directional200/%s.png",name);
}else if(status == 2){
name = String.format("https://cdn.xglpa.com/pars-nft/scene200/%s.png",name);
}else if(status == 3 ){
name = String.format("https://cdn.xglpa.com/pars-nft/nonDirectional500/%s.png",name);
}
map.remove("status");
map.put("name",name);
return R.ok(map);
}
//字符串加密 //字符串加密
public String encrypt(String seed){ public String encrypt(String seed){
String phone = ""; String phone = "";

View File

@ -0,0 +1,99 @@
package com.szxgl.nft.controller;
import com.szxgl.nft.entity.RedisKeyName;
import com.szxgl.nft.entity.UserDO;
import com.szxgl.nft.service.NftPhotoService;
import com.szxgl.nft.service.UserService;
import com.szxgl.nft.utils.R;
import com.szxgl.nft.utils.RedisUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;
@RestController
@RequestMapping("/user")
@Slf4j
public class UserController {
@Autowired
private UserService userService;
@Autowired
private NftPhotoService nftPhotoService;
@Autowired
private RedisUtil redisUtil;
private static final String openidCode = RedisKeyName.getOpenidCode();
/**
* 用户登录
* @param code 验证码
* @return
*/
@PostMapping("/login")
public R login(String openid,String seed,String code, HttpServletRequest request,Integer flag){
// String openid = CookieUtil.getCookie(request.getCookies());
// if(StringUtils.isBlank(openid)){
// log.error("openid为空"+openid);
// throw new ParameterException("openid为空");
// }
if(StringUtils.isBlank(code)){
log.error("验证码不能为空!");
return R.error("验证码不能为空!");
}
if(!redisUtil.hasKey(openidCode+openid)){
log.error("redis缓存中的key不存在"+openidCode+openid);
return R.error("验证码错误或者已过期!");
}
String s = redisUtil.get(openidCode + openid).toString();
if(s.equals(code)){
//用户绑定手机号
userService.addPhone(seed,openid);
//用户绑定NFT图片Hash值
nftPhotoService.addPhonePaintingHash(openid,seed,flag);
}else {
return R.error("验证码错误或者已过期!");
}
return R.ok();
}
/**
* 是否绑定手机号
* @param request
* @return 有值表示已绑定手机号 walletAddr如果有值表示
*/
@PostMapping("/getPhone")
public R getPhone(String openid,HttpServletRequest request){
// String openid = CookieUtil.getCookie(request.getCookies());
// if(StringUtils.isBlank(openid)){
// log.error("openid为空"+openid);
// throw new ParameterException("openid为空");
// }
UserDO userDO = userService.getPhone(openid);
Map<String,Object> map = new HashMap<>();
if(userDO != null){
//手机号已绑定
map.put("walletAddr",userDO.getWalletAddr());
map.put("flag",true);
return R.ok(map);
}else {
//手机号未绑定
map.put("walletAddr","");
map.put("flag",false);
return R.ok(map);
}
}
}

View File

@ -0,0 +1,59 @@
package com.szxgl.nft.controller;
import com.aliyuncs.exceptions.ClientException;
import com.szxgl.nft.entity.RedisKeyName;
import com.szxgl.nft.utils.AliyunSmsUtils;
import com.szxgl.nft.utils.R;
import com.szxgl.nft.utils.RedisUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
@RestController
@RequestMapping("/code")
@Slf4j
public class VerificationCodeController {
@Autowired
private RedisUtil redisUtil;
private static final String openidCode = RedisKeyName.getOpenidCode();
/**
* 获取验证码
* @param seed 手机号
* @return
*/
@PostMapping("/getCode")
public R getCode(String openid, String seed, HttpServletRequest request){
// String openid = CookieUtil.getCookie(request.getCookies());
// if(StringUtils.isBlank(openid)){
// log.error("openid为空"+openid);
// throw new ParameterException("openid为空");
// }
//判断手机号是否为空
if(StringUtils.isBlank(seed)){
log.error("手机号为空:"+seed);
return R.error("手机号为空");
}
//获取验证码
String code = Integer.toString(AliyunSmsUtils.getNewcode());
log.info("发送的验证码为:"+code);
try {
//使用阿里云发送短信
AliyunSmsUtils.sendSms(seed,code);
} catch (ClientException e) {
e.printStackTrace();
}
//把验证码存入redis中
redisUtil.set(openidCode + openid, code, 300);
return R.ok(code);
}
}

View File

@ -1,4 +1,4 @@
package com.szxgl.nft2022.entity; package com.szxgl.nft.entity;
import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data; import lombok.Data;
@ -7,7 +7,7 @@ import java.util.Date;
@Data @Data
@TableName("nft_photo") @TableName("nft_photo")
public class NftPhoto { public class NftPhotoDO {
private Long id; private Long id;
@ -21,16 +21,6 @@ public class NftPhoto {
*/ */
private String paintingHash; private String paintingHash;
/**
* 手机号
*/
private String phone;
/**
* 钱包地址
*/
private String walletAddr;
/** /**
* 状态1定向 2现场 3非定向 * 状态1定向 2现场 3非定向
*/ */

View File

@ -0,0 +1,10 @@
package com.szxgl.nft.entity;
public class RedisKeyName {
private static final String OPENID_CODE = "pars-nft2022:code:";
public static String getOpenidCode() {
return OPENID_CODE;
}
}

View File

@ -1,4 +1,4 @@
package com.szxgl.nft2022.entity; package com.szxgl.nft.entity;
import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data; import lombok.Data;
@ -16,6 +16,16 @@ public class UserDO {
*/ */
private String openid; private String openid;
/**
* 手机号
*/
private String phone;
/**
* 钱包地址
*/
private String walletAddr;
/** /**
* 创建时间 * 创建时间
*/ */

View File

@ -0,0 +1,29 @@
package com.szxgl.nft.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.util.Date;
@Data
@TableName("user_nft_photo")
public class UserNftPhoto {
private Long id;
/**
* 微信用户唯一标识
*/
private String phone;
/**
* nft图片id
*/
private Long nftPhotoId;
/**
* 创建时间
*/
private Date createTime;
}

View File

@ -1,11 +1,9 @@
package com.szxgl.nft2022.exception; package com.szxgl.nft.exception;
import com.szxgl.nft2022.utils.R; import com.szxgl.nft.utils.R;
import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ExceptionHandler;
import javax.servlet.http.HttpServletRequest;
@ControllerAdvice @ControllerAdvice
public class MyAjaxExceptionHandler { public class MyAjaxExceptionHandler {

View File

@ -1,4 +1,4 @@
package com.szxgl.nft2022.exception; package com.szxgl.nft.exception;
public class ParameterException extends RuntimeException { public class ParameterException extends RuntimeException {

View File

@ -1,11 +1,11 @@
package com.szxgl.nft2022.filter; package com.szxgl.nft.filter;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import com.szxgl.nft2022.entity.UserDO; import com.szxgl.nft.entity.UserDO;
import com.szxgl.nft2022.service.UserService; import com.szxgl.nft.service.UserService;
import com.szxgl.nft2022.utils.URIUtil; import com.szxgl.nft.utils.URIUtil;
import com.szxgl.nft2022.utils.Utility; import com.szxgl.nft.utils.Utility;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;

View File

@ -0,0 +1,18 @@
package com.szxgl.nft.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.szxgl.nft.entity.NftPhotoDO;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.Map;
@Mapper
public interface NftPhotoMapper extends BaseMapper<NftPhotoDO> {
Long getRandomHash(Integer flag);
void addNftPhoto(@Param("id") Long id,@Param("seed") String seed);
Map<String,Object> getNftPhotoUrl(String openid);
}

View File

@ -1,7 +1,7 @@
package com.szxgl.nft2022.mapper; package com.szxgl.nft.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.szxgl.nft2022.entity.UserDO; import com.szxgl.nft.entity.UserDO;
import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Mapper;
@Mapper @Mapper

View File

@ -0,0 +1,11 @@
package com.szxgl.nft.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.szxgl.nft.entity.UserNftPhoto;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface UserNftPhotoMapper extends BaseMapper<UserNftPhoto> {
}

View File

@ -0,0 +1,14 @@
package com.szxgl.nft.service;
import com.szxgl.nft.entity.UserNftPhoto;
import java.util.Map;
public interface NftPhotoService {
UserNftPhoto getNftPhoto(String phone);
void addPhonePaintingHash(String seed,String openid,Integer flag);
Map<String,Object> getNftPhotoUrl(String seed);
}

View File

@ -0,0 +1,7 @@
package com.szxgl.nft.service;
public interface UserNftPhotoService {
}

View File

@ -0,0 +1,14 @@
package com.szxgl.nft.service;
import com.szxgl.nft.entity.UserDO;
public interface UserService {
UserDO getUserDo(String openid);
void addUser(UserDO userDO);
void addPhone(String seed, String openid);
UserDO getPhone(String openid);
}

View File

@ -0,0 +1,51 @@
package com.szxgl.nft.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.szxgl.nft.entity.UserNftPhoto;
import com.szxgl.nft.mapper.NftPhotoMapper;
import com.szxgl.nft.mapper.UserNftPhotoMapper;
import com.szxgl.nft.service.NftPhotoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.annotation.Transient;
import org.springframework.stereotype.Service;
import java.util.Map;
@Service
public class NftPhotoServiceImpl implements NftPhotoService {
@Autowired
private NftPhotoMapper nftPhotoMapper;
@Autowired
private UserNftPhotoMapper userNftPhotoMapper;
@Override
public UserNftPhoto getNftPhoto(String phone) {
QueryWrapper<UserNftPhoto> wrapper = new QueryWrapper<>();
wrapper.eq("phone",phone);
return userNftPhotoMapper.selectOne(wrapper);
}
@Override
@Transient
public void addPhonePaintingHash(String seed,String openid,Integer flag) {
UserNftPhoto userNftPhoto = getNftPhoto(seed);
//非定向人群
if(userNftPhoto == null ){
//随机获取图片id图片没有被占用
Long id = nftPhotoMapper.getRandomHash(flag);
//库存充裕
if(id != null ){
//图片绑定手机号
nftPhotoMapper.addNftPhoto(id,seed);
}
}
}
@Override
public Map<String,Object> getNftPhotoUrl(String openid) {
return nftPhotoMapper.getNftPhotoUrl(openid);
}
}

View File

@ -0,0 +1,9 @@
package com.szxgl.nft.service.impl;
import com.szxgl.nft.service.UserNftPhotoService;
import org.springframework.stereotype.Service;
@Service
public class UserNftPhotoServiceImpl implements UserNftPhotoService {
}

View File

@ -0,0 +1,45 @@
package com.szxgl.nft.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.szxgl.nft.entity.UserDO;
import com.szxgl.nft.mapper.UserMapper;
import com.szxgl.nft.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserMapper userMapper;
@Override
public UserDO getUserDo(String openid) {
QueryWrapper<UserDO> wrapper = new QueryWrapper<>();
wrapper.eq("openid",openid);
return userMapper.selectOne(wrapper);
}
@Override
public void addUser(UserDO userDO) {
}
@Override
public void addPhone(String seed, String openid) {
UserDO userDo = getUserDo(openid);
UpdateWrapper<UserDO> wrapper = new UpdateWrapper<>();
wrapper.set("phone",seed);
wrapper.eq("openid",openid);
userMapper.update(userDo,wrapper);
}
@Override
public UserDO getPhone(String openid) {
QueryWrapper<UserDO> wrapper = new QueryWrapper<>();
wrapper.eq("openid",openid);
return userMapper.selectOne(wrapper);
}
}

View File

@ -1,4 +1,4 @@
package com.szxgl.nft2022.utils; package com.szxgl.nft.utils;
import com.aliyuncs.DefaultAcsClient; import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient; import com.aliyuncs.IAcsClient;
@ -7,11 +7,14 @@ import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse;
import com.aliyuncs.exceptions.ClientException; import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.profile.DefaultProfile; import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.profile.IClientProfile; import com.aliyuncs.profile.IClientProfile;
import com.szxgl.nft.exception.ParameterException;
import lombok.extern.slf4j.Slf4j;
/** /**
* 阿里云短信服务 * 阿里云短信服务
* 注意需要 签名名称模版CODE 以及 RAM访问控制中的 AccessKeyID AccessKeySecret * 注意需要 签名名称模版CODE 以及 RAM访问控制中的 AccessKeyID AccessKeySecret
*/ */
@Slf4j
public class AliyunSmsUtils { public class AliyunSmsUtils {
//产品名称:云通信短信API产品,开发者无需替换 //产品名称:云通信短信API产品,开发者无需替换
@ -61,9 +64,10 @@ public class AliyunSmsUtils {
//hint 此处可能会抛出异常注意catch //hint 此处可能会抛出异常注意catch
SendSmsResponse sendSmsResponse = acsClient.getAcsResponse(request); SendSmsResponse sendSmsResponse = acsClient.getAcsResponse(request);
if(sendSmsResponse.getCode()!= null && sendSmsResponse.getCode().equals("OK")){ if(sendSmsResponse.getCode()!= null && sendSmsResponse.getCode().equals("OK")){
System.out.println("短信发送成功!"); log.info("短信发送成功!");
}else { }else {
System.out.println("短信发送失败!"); log.error("短信发送失败!");
throw new ParameterException("短信发送失败!");
} }
return sendSmsResponse; return sendSmsResponse;
} }
@ -100,6 +104,7 @@ public class AliyunSmsUtils {
//以下为测试代码随机生成验证码 //以下为测试代码随机生成验证码
private static int newcode; private static int newcode;
public static int getNewcode() { public static int getNewcode() {
setNewcode();
return newcode; return newcode;
} }
public static void setNewcode(){ public static void setNewcode(){
@ -108,7 +113,7 @@ public class AliyunSmsUtils {
public static void main(String[] args) throws ClientException, InterruptedException { public static void main(String[] args) throws ClientException, InterruptedException {
setNewcode(); //setNewcode();
String code = Integer.toString(getNewcode()); String code = Integer.toString(getNewcode());
System.out.println("发送的验证码为:"+code); System.out.println("发送的验证码为:"+code);
//发短信 //发短信

View File

@ -12,7 +12,7 @@
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
package com.szxgl.nft2022.utils; package com.szxgl.nft.utils;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.security.SecureRandom; import java.security.SecureRandom;

View File

@ -0,0 +1,25 @@
package com.szxgl.nft.utils;
import com.szxgl.nft.exception.ParameterException;
import lombok.extern.slf4j.Slf4j;
import javax.servlet.http.Cookie;
@Slf4j
public class CookieUtil {
public static String getCookie(Cookie[] cookies){
if(cookies == null || cookies.length == 0){
log.error("cookies为空");
throw new ParameterException("cookies为空");
}
String value = "";
for (Cookie cookie : cookies) {
if("openid".equals(cookie.getName())){
value = cookie.getValue();
}
}
return value;
}
}

View File

@ -1,4 +1,4 @@
package com.szxgl.nft2022.utils; package com.szxgl.nft.utils;
import javax.crypto.Cipher; import javax.crypto.Cipher;
import java.security.Key; import java.security.Key;

View File

@ -1,4 +1,4 @@
package com.szxgl.nft2022.utils; package com.szxgl.nft.utils;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;

View File

@ -1,4 +1,4 @@
package com.szxgl.nft2022.utils; package com.szxgl.nft.utils;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;

View File

@ -0,0 +1,707 @@
package com.szxgl.nft.utils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import java.util.*;
import java.util.concurrent.TimeUnit;
/**
* redisTemplate封装
*
* @author MrYshen
*/
@Component
public class RedisUtil {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
public RedisUtil(RedisTemplate<String, Object> redisTemplate) {
this.redisTemplate = redisTemplate;
}
/**
* 指定缓存失效时间
*
* @param key
* @param time 时间()
* @return
*/
public boolean expire(String key, long time) {
try {
if (time > 0) {
redisTemplate.expire(key, time, TimeUnit.SECONDS);
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 根据key 获取过期时间
*
* @param key 不能为null
* @return 时间() 返回0代表为永久有效
*/
public long getExpire(String key) {
return redisTemplate.getExpire(key, TimeUnit.SECONDS);
}
/**
* 判断key是否存在
*
* @param key
* @return true 存在 false不存在
*/
public boolean hasKey(String key) {
try {
return redisTemplate.hasKey(key);
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 删除缓存
*
* @param key 可以传一个值 或多个
*/
@SuppressWarnings("unchecked")
public void del(String... key) {
if (key != null && key.length > 0) {
if (key.length == 1) {
redisTemplate.delete(key[0]);
} else {
redisTemplate.delete((Collection<String>) CollectionUtils.arrayToList(key));
}
}
}
//============================String=============================
/**
* 普通缓存获取
*
* @param key
* @return
*/
public Object get(String key) {
return key == null ? null : redisTemplate.opsForValue().get(key);
}
/**
* 普通缓存放入
*
* @param key
* @param value
* @return true成功 false失败
*/
public boolean set(String key, Object value) {
try {
redisTemplate.opsForValue().set(key, value);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 普通缓存放入并设置时间
*
* @param key
* @param value
* @param time 时间() time要大于0 如果time小于等于0 将设置无限期
* @return true成功 false 失败
*/
public boolean set(String key, Object value, long time) {
try {
if (time > 0) {
redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
} else {
set(key, value);
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 递增
*
* @param key
* @param delta 要增加几(大于0)
* @return
*/
public long incr(String key, long delta) {
if (delta < 0) {
throw new RuntimeException("递增因子必须大于0");
}
return redisTemplate.opsForValue().increment(key, delta);
}
/**
* 递减
*
* @param key
* @param delta 要减少几(小于0)
* @return
*/
public long decr(String key, long delta) {
if (delta < 0) {
throw new RuntimeException("递减因子必须大于0");
}
return redisTemplate.opsForValue().increment(key, -delta);
}
//================================Map=================================
/**
* HashGet
*
* @param key 不能为null
* @param item 不能为null
* @return
*/
public Object hget(String key, String item) {
return redisTemplate.opsForHash().get(key, item);
}
/**
* 获取hashKey对应的所有键值
*
* @param key
* @return 对应的多个键值
*/
public Map<Object, Object> hmget(String key) {
return redisTemplate.opsForHash().entries(key);
}
/**
* HashSet
*
* @param key
* @param map 对应多个键值
* @return true 成功 false 失败
*/
public boolean hmset(String key, Map<String, Object> map) {
try {
redisTemplate.opsForHash().putAll(key, map);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* HashSet 并设置时间
*
* @param key
* @param map 对应多个键值
* @param time 时间()
* @return true成功 false失败
*/
public boolean hmset(String key, Map<String, Object> map, long time) {
try {
redisTemplate.opsForHash().putAll(key, map);
if (time > 0) {
expire(key, time);
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 向一张hash表中放入数据,如果不存在将创建
*
* @param key
* @param item
* @param value
* @return true 成功 false失败
*/
public boolean hset(String key, String item, Object value) {
try {
redisTemplate.opsForHash().put(key, item, value);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 向一张hash表中放入数据,如果不存在将创建
*
* @param key
* @param item
* @param value
* @param time 时间() 注意:如果已存在的hash表有时间,这里将会替换原有的时间
* @return true 成功 false失败
*/
public boolean hset(String key, String item, Object value, long time) {
try {
redisTemplate.opsForHash().put(key, item, value);
if (time > 0) {
expire(key, time);
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 删除hash表中的值
*
* @param key 不能为null
* @param item 可以使多个 不能为null
*/
public void hdel(String key, Object... item) {
redisTemplate.opsForHash().delete(key, item);
}
/**
* 判断hash表中是否有该项的值
*
* @param key 不能为null
* @param item 不能为null
* @return true 存在 false不存在
*/
public boolean hHasKey(String key, String item) {
return redisTemplate.opsForHash().hasKey(key, item);
}
/**
* hash递增 如果不存在,就会创建一个 并把新增后的值返回
*
* @param key
* @param item
* @param by 要增加几(大于0)
* @return
*/
public double hincr(String key, String item, double by) {
return redisTemplate.opsForHash().increment(key, item, by);
}
/**
* hash递减
*
* @param key
* @param item
* @param by 要减少记(小于0)
* @return
*/
public double hdecr(String key, String item, double by) {
return redisTemplate.opsForHash().increment(key, item, -by);
}
//============================set=============================
/**
* 根据key获取Set中的所有值
*
* @param key
* @return
*/
public Set<Object> sGet(String key) {
try {
return redisTemplate.opsForSet().members(key);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 根据value从一个set中查询,是否存在
*
* @param key
* @param value
* @return true 存在 false不存在
*/
public boolean sHasKey(String key, Object value) {
try {
return redisTemplate.opsForSet().isMember(key, value);
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 将数据放入set缓存
*
* @param key
* @param values 可以是多个
* @return 成功个数
*/
public long sSet(String key, Object... values) {
try {
return redisTemplate.opsForSet().add(key, values);
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
/**
* 将set数据放入缓存
*
* @param key
* @param time 时间()
* @param values 可以是多个
* @return 成功个数
*/
public long sSetAndTime(String key, long time, Object... values) {
try {
Long count = redisTemplate.opsForSet().add(key, values);
if (time > 0) {
expire(key, time);
}
return count;
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
/**
* 获取set缓存的长度
*
* @param key
* @return
*/
public long sGetSetSize(String key) {
try {
return redisTemplate.opsForSet().size(key);
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
/**
* 移除值为value的
*
* @param key
* @param values 可以是多个
* @return 移除的个数
*/
public long setRemove(String key, Object... values) {
try {
Long count = redisTemplate.opsForSet().remove(key, values);
return count;
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
//===============================list=================================
/**
* 获取list缓存的内容
*
* @param key
* @param start 开始
* @param end 结束 0 -1代表所有值
* @return
*/
public List<Object> lGet(String key, long start, long end) {
try {
return redisTemplate.opsForList().range(key, start, end);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 获取list缓存的长度
*
* @param key
* @return
*/
public long lGetListSize(String key) {
try {
return redisTemplate.opsForList().size(key);
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
/**
* 通过索引 获取list中的值
*
* @param key
* @param index 索引 index>=0时 0 表头1 第二个元素依次类推index<0时-1表尾-2倒数第二个元素依次类推
* @return
*/
public Object lGetIndex(String key, long index) {
try {
return redisTemplate.opsForList().index(key, index);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 将list放入缓存
*
* @param key
* @param value
* @return
*/
public boolean lSetMIn(String key, Object value) {
try {
redisTemplate.opsForList().rightPush(key, value);
expire(key, 60);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 将list放入缓存
*
* @param key
* @param value
* @return
*/
public boolean lSet(String key, Object value) {
try {
redisTemplate.opsForList().rightPush(key, value);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 将list放入缓存
*
* @param key
* @param value
* @param time 时间()
* @return
*/
public boolean lSet(String key, Object value, long time) {
try {
redisTemplate.opsForList().rightPush(key, value);
if (time > 0) {
expire(key, time);
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 将list放入缓存
*
* @param key
* @param value
* @return
*/
public boolean lSetList(String key, List<Object> value) {
try {
redisTemplate.opsForList().rightPushAll(key, value);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 将list放入缓存
*
* @param key
* @param value
* @param time 时间()
* @return
*/
public boolean lSetList(String key, List<Object> value, long time) {
try {
redisTemplate.opsForList().rightPushAll(key, value);
if (time > 0) {
expire(key, time);
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 根据索引修改list中的某条数据
*
* @param key
* @param index 索引
* @param value
* @return
*/
public boolean lUpdateIndex(String key, long index, Object value) {
try {
redisTemplate.opsForList().set(key, index, value);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 根据索引弹出list中的首条数据
*
* @param key
* @param index 等待时间
* @return
*/
public Object lPop(String key, long index) {
try {
Object o = redisTemplate.opsForList().leftPop(key, index, TimeUnit.SECONDS);
return o;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 移除N个值为value
*
* @param key
* @param count 移除多少个
* @param value
* @return 移除的个数
*/
public long lRemove(String key, long count, Object value) {
try {
Long remove = redisTemplate.opsForList().remove(key, count, value);
return remove;
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
//Zset 根据 socre 排序 不重复 每个元素附加一个 socre double类型的属性(double 可以重复)
/**
* 添加 ZSet 元素
* @param key
* @param value
* @param score
*/
public boolean addZSet(String key,Object value,double score){
return redisTemplate.opsForZSet().add(key, value, score);
}
/**
* 批量添加 Zset <br>
* Set<TypedTuple<V>> tuples = new HashSet<>();<br>
* TypedTuple<V> objectTypedTuple1 = new DefaultTypedTuple<V>("zset-5",9.6);<br>
* tuples.add(objectTypedTuple1);
* @param key
* @param tuples
* @return
*/
public Long AddAllZset(String key,Set<ZSetOperations.TypedTuple<Object>> tuples){
return redisTemplate.opsForZSet().add(key, tuples);
}
/**
* Zset 删除一个或多个元素
* @param key
* @param values
* @return
*/
public Long removeZset(String key,Object ...values){
return redisTemplate.opsForZSet().remove(key, values);
}
/**
* 获取 key 中指定 value 的排名(从0开始,从小到大排序)
* @param key
* @param value
* @return
*/
public Long rank(String key,Object value){
return redisTemplate.opsForZSet().rank(key, value);
}
/**
* 获取 key 中指定 value 的排名(从0开始,从大到小排序)
* @param key
* @param value
* @return
*/
public Long reverseRank(String key,Object value){
return redisTemplate.opsForZSet().reverseRank(key, value);
}
/**
* 获取索引区间内的排序结果集合(从0开始,从小到大,带上分数)
* @param key
* @param start
* @param end
* @return
*/
public Set<ZSetOperations.TypedTuple<Object>> rangeWithScores(String key, long start, long end){
return redisTemplate.opsForZSet().rangeWithScores(key, start, end);
}
/**
* 获取索引区间内的排序结果集合(从0开始,从大到小,带上分数)
* @param key
* @param start
* @param end
* @return
*/
public Set<ZSetOperations.TypedTuple<Object>> reverseRangeWithScores(String key, long start, long end){
return redisTemplate.opsForZSet().reverseRangeWithScores(key, start, end);
}
/**
* score的增加or减少 zincrby
*
* @param key
* @param value
* @param score
*/
public Double incrScore(String key,String value, double score){
return redisTemplate.opsForZSet().incrementScore(key, value, score);
}
/**
* 获取指定成员的 score
* @param key
* @param value
* @return
*/
public Double score(String key,Object value){
return redisTemplate.opsForZSet().score(key, value);
}
}

View File

@ -3,7 +3,7 @@
// (powered by FernFlower decompiler) // (powered by FernFlower decompiler)
// //
package com.szxgl.nft2022.utils; package com.szxgl.nft.utils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
@ -54,4 +54,5 @@ public class URIUtil {
return o.toString(); return o.toString();
} }
} }

View File

@ -1,4 +1,4 @@
package com.szxgl.nft2022.utils; package com.szxgl.nft.utils;
import org.apache.commons.codec.digest.DigestUtils; import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.codec.digest.UnixCrypt; import org.apache.commons.codec.digest.UnixCrypt;

View File

@ -1,9 +0,0 @@
package com.szxgl.nft2022.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.szxgl.nft2022.entity.NftPhoto;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface NftPhotoMapper extends BaseMapper<NftPhoto> {
}

View File

@ -1,9 +0,0 @@
package com.szxgl.nft2022.service;
import com.szxgl.nft2022.entity.NftPhoto;
public interface NftPhotoService {
NftPhoto getNftPhoto(String phone);
}

View File

@ -1,11 +0,0 @@
package com.szxgl.nft2022.service;
import com.szxgl.nft2022.entity.UserDO;
public interface UserService {
UserDO getUserDo(String openid);
void addUser(UserDO userDO);
}

View File

@ -1,22 +0,0 @@
package com.szxgl.nft2022.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.szxgl.nft2022.entity.NftPhoto;
import com.szxgl.nft2022.mapper.NftPhotoMapper;
import com.szxgl.nft2022.service.NftPhotoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class NftPhotoServiceImpl implements NftPhotoService {
@Autowired
private NftPhotoMapper nftPhotoMapper;
@Override
public NftPhoto getNftPhoto(String phone) {
QueryWrapper<NftPhoto> wrapper = new QueryWrapper<>();
wrapper.eq("phone",phone);
return nftPhotoMapper.selectOne(wrapper);
}
}

View File

@ -1,28 +0,0 @@
package com.szxgl.nft2022.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.szxgl.nft2022.entity.UserDO;
import com.szxgl.nft2022.mapper.UserMapper;
import com.szxgl.nft2022.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserMapper userMapper;
@Override
public UserDO getUserDo(String openid) {
QueryWrapper<UserDO> wrapper = new QueryWrapper<>();
wrapper.eq("openid",openid);
return userMapper.selectOne(wrapper);
}
@Override
public void addUser(UserDO userDO) {
}
}

View File

@ -36,6 +36,20 @@ spring:
max-file-size: 500MB max-file-size: 500MB
max-request-size: 500MB max-request-size: 500MB
redis:
database: 0
host: 39.108.110.167
port: 8266
password: 'Qiween@4531871' # 密码
timeout: 6000ms # 连接超时时长(毫秒)
jedis:
pool:
max-active: 1000 # 连接池最大连接数(使用负值表示没有限制)
max-wait: -1ms # 连接池最大阻塞等待时间(使用负值表示没有限制)
max-idle: 10 # 连接池中的最大空闲连接
min-idle: 5 # 连接池中的最小空闲连接
wx: wx:
appid: wx35766a64d73d08a9 appid: wx35766a64d73d08a9

View File

@ -1,13 +1,13 @@
server: server:
port: 8660 port: 8660
servlet: servlet:
context-path: /pars-nft2022 context-path: /pars-nft
spring: spring:
# # 允许预检请求 # # 允许预检请求
# mvc: # mvc:
# dispatch-options-request: true # dispatch-options-request: true
jmx: jmx:
default-domain: nft2022 default-domain: nft
profiles: profiles:
active: dev active: dev
# mvc: # mvc:

View File

@ -8,9 +8,9 @@
<Properties> <Properties>
<!-- 格式化输出:%date表示日期%thread表示线程名%-5level级别从左显示5个字符宽度 %msg日志消息%n是换行符--> <!-- 格式化输出:%date表示日期%thread表示线程名%-5level级别从左显示5个字符宽度 %msg日志消息%n是换行符-->
<!-- %logger{36} 表示 Logger 名字最长36个字符 --> <!-- %logger{36} 表示 Logger 名字最长36个字符 -->
<property name="LOG_PATTERN" value="[pars-nft2022]%date{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n" /> <property name="LOG_PATTERN" value="[pars-nft]%date{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n" />
<!-- 定义日志存储的路径tomcat环境下用${sys:catalina.home}本地测试可定义到target目录下方便清理与忽略日志文件 --> <!-- 定义日志存储的路径tomcat环境下用${sys:catalina.home}本地测试可定义到target目录下方便清理与忽略日志文件 -->
<property name="FILE_PATH" value="${catalina.home}/logs/pars-nft2022/" /> <property name="FILE_PATH" value="${catalina.home}/logs/pars-nft/" />
</Properties> </Properties>
<appenders> <appenders>
@ -23,12 +23,12 @@
</console> </console>
<!--文件会打印出所有信息这个log每次运行程序会自动清空由append属性决定适合临时测试用--> <!--文件会打印出所有信息这个log每次运行程序会自动清空由append属性决定适合临时测试用-->
<File name="Filelog" fileName="${sys:catalina.home}/logs/pars-nft2022/test.log" append="false"> <File name="Filelog" fileName="${sys:catalina.home}/logs/pars-nft/test.log" append="false">
<PatternLayout pattern="${LOG_PATTERN}"/> <PatternLayout pattern="${LOG_PATTERN}"/>
</File> </File>
<!-- 这个会打印出所有的info及以下级别的信息每次大小超过size则这size大小的日志会自动存入按年份-月份建立的文件夹下面并进行压缩,作为存档--> <!-- 这个会打印出所有的info及以下级别的信息每次大小超过size则这size大小的日志会自动存入按年份-月份建立的文件夹下面并进行压缩,作为存档-->
<RollingFile name="RollingFileInfo" fileName="${sys:catalina.home}/logs/pars-nft2022/info.log" filePattern="${FILE_PATH}/info-%d{yyyyMMdd}_%i.log.gz"> <RollingFile name="RollingFileInfo" fileName="${sys:catalina.home}/logs/pars-nft/info.log" filePattern="${FILE_PATH}/info-%d{yyyyMMdd}_%i.log.gz">
<!--控制台只输出level及以上级别的信息onMatch其他的直接拒绝onMismatch--> <!--控制台只输出level及以上级别的信息onMatch其他的直接拒绝onMismatch-->
<ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY"/> <ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY"/>
<PatternLayout pattern="${LOG_PATTERN}"/> <PatternLayout pattern="${LOG_PATTERN}"/>
@ -42,7 +42,7 @@
</RollingFile> </RollingFile>
<!-- 这个会打印出所有的error及以下级别的信息每次大小超过size则这size大小的日志会自动存入按年份-月份建立的文件夹下面并进行压缩,作为存档--> <!-- 这个会打印出所有的error及以下级别的信息每次大小超过size则这size大小的日志会自动存入按年份-月份建立的文件夹下面并进行压缩,作为存档-->
<RollingFile name="RollingFileError" fileName="${sys:catalina.home}/logs/pars-nft2022/error.log" filePattern="${FILE_PATH}/error-%d{yyyyMMdd}_%i.log.gz"> <RollingFile name="RollingFileError" fileName="${sys:catalina.home}/logs/pars-nft/error.log" filePattern="${FILE_PATH}/error-%d{yyyyMMdd}_%i.log.gz">
<!--控制台只输出level及以上级别的信息onMatch其他的直接拒绝onMismatch--> <!--控制台只输出level及以上级别的信息onMatch其他的直接拒绝onMismatch-->
<ThresholdFilter level="error" onMatch="ACCEPT" onMismatch="DENY"/> <ThresholdFilter level="error" onMatch="ACCEPT" onMismatch="DENY"/>
<PatternLayout pattern="${LOG_PATTERN}"/> <PatternLayout pattern="${LOG_PATTERN}"/>

View File

@ -0,0 +1,50 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.szxgl.nft.mapper.NftPhotoMapper">
<select id="getRandomHash" resultType="java.lang.Long">
SELECT
np.id
FROM
user_nft_photo up
RIGHT JOIN nft_photo np ON up.nft_photo_id = np.id
WHERE
( LENGTH( up.phone ) = 0 OR up.phone IS NULL )
AND np.STATUS = #{flag}
ORDER BY
rand()
LIMIT 1
</select>
<insert id="addNftPhoto">
insert into user_nft_photo
(
phone,
nft_photo_id,
create_time
)
values
(
#{seed},
#{id},
now()
)
</insert>
<select id="getPhone" resultType="com.szxgl.nft.entity.UserDO">
select * from user where openid = #{openid}
</select>
<select id="getNftPhotoUrl" resultType="java.util.Map">
SELECT
np.`name`,
np.status,
u.wallet_addr
FROM
nft_photo np
INNER JOIN user_nft_photo up ON np.id = up.nft_photo_id
INNER JOIN `user` u ON up.phone = u.phone
where u.openid = '1234'
</select>
</mapper>