Browse Source

添加私钥功能,设置上链阀值。添加MD5加密

master
long 3 years ago
parent
commit
4471cbb9a7
  1. 2
      conflux-admin/src/main/java/com/conflux/RuoYiApplication.java
  2. 15
      conflux-admin/src/main/java/com/conflux/web/controller/api/ConfluxAipController.java
  3. 1
      conflux-admin/src/main/java/com/conflux/web/controller/collect/service/impl/CollectConfigServiceImpl.java
  4. 34
      conflux-admin/src/main/java/com/conflux/web/controller/contract/domain/ContractConfig.java
  5. 2
      conflux-admin/src/main/java/com/conflux/web/controller/nft/domain/CheckArgs.java
  6. 2
      conflux-admin/src/main/java/com/conflux/web/controller/nft/domain/ConfluxArt.java
  7. 2
      conflux-admin/src/main/java/com/conflux/web/controller/nft/mapper/NftLogMapper.java
  8. 5
      conflux-admin/src/main/java/com/conflux/web/controller/nft/service/ConfluxService.java
  9. 2
      conflux-admin/src/main/java/com/conflux/web/controller/nft/service/INftLogService.java
  10. 94
      conflux-admin/src/main/java/com/conflux/web/controller/nft/service/impl/ConfluxServiceImpl.java
  11. 5
      conflux-admin/src/main/java/com/conflux/web/controller/nft/service/impl/NftLogServiceImpl.java
  12. 104
      conflux-admin/src/main/java/com/conflux/web/controller/privateKey/controller/PrivateKeyController.java
  13. 37
      conflux-admin/src/main/java/com/conflux/web/controller/privateKey/domain/PrivateKey.java
  14. 68
      conflux-admin/src/main/java/com/conflux/web/controller/privateKey/mapper/PrivateKeyMapper.java
  15. 67
      conflux-admin/src/main/java/com/conflux/web/controller/privateKey/service/IPrivateKeyService.java
  16. 156
      conflux-admin/src/main/java/com/conflux/web/controller/privateKey/service/impl/PrivateKeyServiceImpl.java
  17. 50
      conflux-admin/src/main/java/com/conflux/web/controller/util/AESUtil.java
  18. 194
      conflux-admin/src/main/java/com/conflux/web/controller/util/ScheduledTask.java
  19. 9
      conflux-admin/src/main/resources/application-druid.yml
  20. 9
      conflux-admin/src/main/resources/application-prod.yml
  21. 1
      conflux-admin/src/main/resources/application.yml
  22. 64
      conflux-common/src/main/java/com/conflux/common/utils/sign/Md5Utils.java
  23. 43
      conflux-system/src/main/resources/mapper/system/ContractConfigMapper.xml
  24. 5
      conflux-system/src/main/resources/mapper/system/NftLogMapper.xml
  25. 79
      conflux-system/src/main/resources/mapper/system/PrivateKeyMapper.xml

2
conflux-admin/src/main/java/com/conflux/RuoYiApplication.java

@ -5,6 +5,7 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
/**
@ -13,6 +14,7 @@ import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
* @author conflux
*/
@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class })
@EnableScheduling
public class RuoYiApplication
{
public static void main(String[] args)

15
conflux-admin/src/main/java/com/conflux/web/controller/api/ConfluxAipController.java

@ -3,6 +3,7 @@ package com.conflux.web.controller.api;
import com.conflux.common.core.domain.AjaxResult;
import com.conflux.web.controller.nft.domain.CheckArgs;
import com.conflux.web.controller.nft.service.ConfluxService;
import com.conflux.web.controller.privateKey.domain.PrivateKey;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
@ -45,19 +46,19 @@ public class ConfluxAipController {
* @return
*/
@ApiOperation("获取token")
@GetMapping("/getToken")
public AjaxResult getToken() {
return confluxService.getToken();
@PostMapping("/getToken")
public AjaxResult getToken(@RequestBody PrivateKey privateKey) {
return confluxService.getToken(privateKey);
}
/**
* 查询id是否铸造成功
* @param ids
* @param checkArgs
* @return
*/
@ApiOperation("查询id是否铸造成功")
@GetMapping("/getNftStatus")
public AjaxResult getNftStatus(@RequestParam("ids") String[] ids){
return confluxService.getNftStatus(ids);
@PostMapping("/getNftStatus")
public AjaxResult getNftStatus(@RequestBody CheckArgs checkArgs){
return confluxService.getNftStatus(checkArgs);
}
}

1
conflux-admin/src/main/java/com/conflux/web/controller/collect/service/impl/CollectConfigServiceImpl.java

@ -53,6 +53,7 @@ public class CollectConfigServiceImpl implements ICollectConfigService {
@Override
public int insertCollectConfig(CollectConfig collectConfig) {
collectConfig.setCreateTime(System.currentTimeMillis());
return collectConfigMapper.insertCollectConfig(collectConfig);
}

34
conflux-admin/src/main/java/com/conflux/web/controller/contract/domain/ContractConfig.java

@ -10,30 +10,48 @@ import java.math.BigInteger;
/**
* 合约私钥配置对象 contract_config
*
*
* @author conflux
* @date 2022-05-31
*/
@Data
public class ContractConfig extends BaseEntity
{
public class ContractConfig extends BaseEntity {
private static final long serialVersionUID = 1L;
/** $column.columnComment */
/**
* $column.columnComment
*/
private Long id;
/**单位名称**/
/**
* 单位名称
**/
private String unitName;
/** 合约地址 */
/**
* 合约地址
*/
@Excel(name = "合约地址")
private String contract;
/** 拥有者 */
/**
* 拥有者
*/
@Excel(name = "拥有者")
private String owner;
private BigInteger gasPrice;
/** 私钥 */
/**
* 私钥
*/
@Excel(name = "私钥")
private String privateKey;
/**
* 阀值
*/
private Integer threshold;
/** 上链的总阀值 */
@Excel(name = "上链的总阀值")
private Integer totalThreshold;
}

2
conflux-admin/src/main/java/com/conflux/web/controller/nft/domain/CheckArgs.java

@ -13,4 +13,6 @@ public class CheckArgs {
private String timesTamp;
private String sign;
private String[] ids;
private String appId;
private String privateKey;
}

2
conflux-admin/src/main/java/com/conflux/web/controller/nft/domain/ConfluxArt.java

@ -33,7 +33,7 @@ import java.util.List;
* @Date 2022 05 31
**/
public class ConfluxArt extends Contract {
public static final String AESKEY="CONFLUX@123";
public static final String AESKEY="CONFLUX@12345678";
public static final String SIGN = "0x7803ec04eed7bd4f3fd9c3fc824408a80e0b20b599b5e726cbaa609d48a2082d";

2
conflux-admin/src/main/java/com/conflux/web/controller/nft/mapper/NftLogMapper.java

@ -60,4 +60,6 @@ public interface NftLogMapper
* @return 结果
*/
public int deleteNftLogByIds(Long[] ids);
public int selectSum(String unitName);
}

5
conflux-admin/src/main/java/com/conflux/web/controller/nft/service/ConfluxService.java

@ -2,6 +2,7 @@ package com.conflux.web.controller.nft.service;
import com.conflux.common.core.domain.AjaxResult;
import com.conflux.web.controller.nft.domain.CheckArgs;
import com.conflux.web.controller.privateKey.domain.PrivateKey;
/**
* @Author _007long
@ -18,7 +19,7 @@ public interface ConfluxService {
* 获取token
* @return
*/
AjaxResult getToken();
AjaxResult getToken(PrivateKey privateKey);
AjaxResult getNftStatus(String[] ids);
AjaxResult getNftStatus(CheckArgs checkArgs);
}

2
conflux-admin/src/main/java/com/conflux/web/controller/nft/service/INftLogService.java

@ -60,4 +60,6 @@ public interface INftLogService
* @return 结果
*/
public int deleteNftLogById(Long id);
public int selectSum(String unitName);
}

94
conflux-admin/src/main/java/com/conflux/web/controller/nft/service/impl/ConfluxServiceImpl.java

@ -3,6 +3,7 @@ package com.conflux.web.controller.nft.service.impl;
import cn.hutool.core.date.DateUtil;
import com.conflux.common.core.domain.AjaxResult;
import com.conflux.common.utils.StringUtils;
import com.conflux.common.utils.sign.Md5Utils;
import com.conflux.common.utils.uuid.IdUtils;
import com.conflux.web.controller.collect.domain.CollectConfig;
import com.conflux.web.controller.collect.service.ICollectConfigService;
@ -14,6 +15,8 @@ import com.conflux.web.controller.nft.service.ConfluxService;
import com.conflux.web.controller.nft.service.IHandlerStrategy;
import com.conflux.web.controller.nft.service.INftCollectionService;
import com.conflux.web.controller.nft.service.INftLogService;
import com.conflux.web.controller.privateKey.domain.PrivateKey;
import com.conflux.web.controller.privateKey.service.IPrivateKeyService;
import com.conflux.web.controller.util.AESUtil;
import com.conflux.web.controller.util.AddressUtil;
import com.conflux.web.controller.util.CfxUtils;
@ -64,6 +67,8 @@ public class ConfluxServiceImpl implements ConfluxService {
private IHandlerStrategy iHandlerStrategy;
@Autowired
private ThreadPoolTaskExecutor executor;
@Autowired
private IPrivateKeyService privateKeyService;
@SneakyThrows
@Override
@ -73,38 +78,56 @@ public class ConfluxServiceImpl implements ConfluxService {
if (null == checkArgs) {
return AjaxResult.error("参数为空!");
}
if (StringUtils.isEmpty(checkArgs.getToken()) || StringUtils.isEmpty(checkArgs.getIds()) || StringUtils.isEmpty(checkArgs.getSign()) || StringUtils.isEmpty(checkArgs.getTimesTamp())) {
//判断必传参数
if (StringUtils.isEmpty(checkArgs.getToken()) || StringUtils.isEmpty(checkArgs.getIds()) ||
StringUtils.isEmpty(checkArgs.getSign()) || StringUtils.isEmpty(checkArgs.getTimesTamp()) ||
StringUtils.isEmpty(checkArgs.getUnitName()) || StringUtils.isEmpty(checkArgs.getAppId()) ||
StringUtils.isEmpty(checkArgs.getPrivateKey())) {
return AjaxResult.error("参数缺失!");
}
if (checkArgs.getIds().length > 100) {
return AjaxResult.error("上链数量超出100!");
ContractConfig contractConfig = contractConfigService.selectContractConfigByUnitName(checkArgs.getUnitName());
if (null == contractConfig) {
return AjaxResult.error("合约不存在!");
}
if (checkArgs.getIds().length > contractConfig.getThreshold()) {
return AjaxResult.error("单次上链数量超出上限!");
}
int sum = nftLogService.selectSum(checkArgs.getUnitName());
if (sum>contractConfig.getTotalThreshold()){
return AjaxResult.error("上链总数量超出上限!");
}
String[] ids = checkArgs.getIds();
List<NftCollection> nftCollections = nftCollectionService.selectNftCollectionListByIds(ids, null);
if (nftCollections.size()>0) {
if (nftCollections.size() > 0) {
List list = new ArrayList();
for (NftCollection n : nftCollections) {
list.add(n.getInformationTableId());
}
return AjaxResult.error("已经上链的id", list);
}
String checkArgsToken = AESUtil.decrypt(checkArgs.getToken(), ConfluxArt.AESKEY);
String token = (String) redisUtils.get(checkArgsToken);
String checkArgsToken = AESUtil.Decrypt(checkArgs.getToken(), ConfluxArt.AESKEY);
String token = (String) redisUtils.get(checkArgs.getAppId());//通过私钥获取缓存token
PrivateKey privateKey = privateKeyService.selectPrivateKeyByAppId(checkArgs.getAppId());
if (null==privateKey){
return AjaxResult.error("appId错误!");
}
String md5Key = Md5Utils.md5Salt(privateKey.getPrivateKey());
if(!checkArgs.getPrivateKey().equals(md5Key)){
return AjaxResult.error("privateKey私钥出错!");
}
String redisSign = (String) redisUtils.get(checkArgs.getPrivateKey());//通过密钥获取sign签名
if (null == token) {
return AjaxResult.error("token已过期!");
}
String sign = AESUtil.decrypt(checkArgs.getSign(), ConfluxArt.AESKEY);
String sign = AESUtil.Decrypt(checkArgs.getSign(), ConfluxArt.AESKEY);
//校验token和sign签名
if (token.equals(checkArgsToken) && sign.equals(ConfluxArt.SIGN)) {
if (token.equals(checkArgsToken) && sign.equals(redisSign)) {
//校验时间戳
long time = Long.valueOf(checkArgs.getTimesTamp());
long timesTamp = System.currentTimeMillis();
if (timesTamp - time > 30000l) {
return AjaxResult.error("时间参数错误!");
}
//删除缓存
redisUtils.del(checkArgsToken);
redisUtils.del(sign);
//判断上链的数量
CollectConfig collectConfig = collectConfigService.selectCollectConfigByStatus();
if (collectConfig.getMintPause()) {
@ -113,7 +136,7 @@ public class ConfluxServiceImpl implements ConfluxService {
return AjaxResult.error("pause参数异常!");
}
Cfx cfx = Cfx.create(collectConfig.getNode(), 3, 1000);
ContractConfig contractConfig = contractConfigService.selectContractConfigByUnitName(checkArgs.getUnitName());
Account account = Account.create(cfx, AESUtil.decrypt(contractConfig.getPrivateKey()));
Account.Option opt = new Account.Option();
opt.withValue(BigInteger.ZERO);
@ -173,24 +196,52 @@ public class ConfluxServiceImpl implements ConfluxService {
});
return AjaxResult.success("上链成功!");
}
return AjaxResult.error();
return AjaxResult.error("token或sign签名失效!");
}
@Override
public AjaxResult getToken() {
public AjaxResult getToken(PrivateKey privateKey) {
if (null == privateKey.getAppId() || null == privateKey.getPrivateKey()) {
return AjaxResult.error("参数缺失!");
}
PrivateKey privateKey1 = privateKeyService.selectPrivateKeyByAppId(privateKey.getAppId());
if (null==privateKey1){
return AjaxResult.error("appId错误!");
}
String md5Key = Md5Utils.md5Salt(privateKey1.getPrivateKey());
if (!privateKey.getPrivateKey().equals(md5Key)){
return AjaxResult.error("privateKey错误!");
}
Map<String, Object> map = new HashMap<>();
String token = IdUtils.fastUUID();
String token = IdUtils.fastSimpleUUID();
long time = System.currentTimeMillis();
map.put("token", token);
map.put("timesTamp", time);
map.put("sign", ConfluxArt.SIGN);
redisUtils.set(token, token);
try {
map.put("sign", AESUtil.encrypt(ConfluxArt.SIGN + time));
redisUtils.set(privateKey.getAppId(), token,360000l);//缓存一小时
redisUtils.set(md5Key, AESUtil.encrypt(ConfluxArt.SIGN + time),360000l);
} catch (Exception e) {
e.printStackTrace();
}
return AjaxResult.success(map);
}
@Override
public AjaxResult getNftStatus(String[] ids) {
List<NftCollection> nftCollections = nftCollectionService.selectNftCollectionListByIds(ids, 2);
public AjaxResult getNftStatus(CheckArgs checkArgs) {
if(StringUtils.isEmpty(checkArgs.getIds())||StringUtils.isEmpty(checkArgs.getAppId())||StringUtils.isEmpty(checkArgs.getPrivateKey())){
return AjaxResult.error("参数缺失!");
}
PrivateKey privateKey = privateKeyService.selectPrivateKeyByAppId(checkArgs.getAppId());
if (null==privateKey){
return AjaxResult.error("appId错误!");
}
String md5Key = Md5Utils.md5Salt(privateKey.getPrivateKey());
if(!checkArgs.getPrivateKey().equals(md5Key)){
return AjaxResult.error("privateKey私钥出错!");
}
List<NftCollection> nftCollections = nftCollectionService.selectNftCollectionListByIds(checkArgs.getIds(), 2);
if (nftCollections.size() > 0) {
List list = new ArrayList();
for (NftCollection n : nftCollections) {
@ -200,6 +251,7 @@ public class ConfluxServiceImpl implements ConfluxService {
}
return AjaxResult.error("暂无数据");
}
public boolean executeMakeUp(String contract, String markName) {
log.info("[dispatchHandler]{}", "开始监听数据");
CollectConfig collect = (CollectConfig) redisUtils.get(contract);
@ -247,9 +299,9 @@ public class ConfluxServiceImpl implements ConfluxService {
long from = 0l;
if (null == redisUtils.get(keyNumber)) {
from = collect.getEpochNumber();
}else {
} else {
Integer number = (Integer) redisUtils.get(keyNumber);
from= Long.valueOf(number);
from = Long.valueOf(number);
}
// Invoke cfx method
BigInteger epoch = cfx.getEpochNumber().sendAndGet();

5
conflux-admin/src/main/java/com/conflux/web/controller/nft/service/impl/NftLogServiceImpl.java

@ -94,4 +94,9 @@ public class NftLogServiceImpl implements INftLogService
{
return nftLogMapper.deleteNftLogById(id);
}
@Override
public int selectSum(String unitName) {
return nftLogMapper.selectSum(unitName);
}
}

104
conflux-admin/src/main/java/com/conflux/web/controller/privateKey/controller/PrivateKeyController.java

@ -0,0 +1,104 @@
package com.conflux.web.controller.privateKey.controller;
import java.util.List;
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.conflux.common.annotation.Log;
import com.conflux.common.core.controller.BaseController;
import com.conflux.common.core.domain.AjaxResult;
import com.conflux.common.enums.BusinessType;
import com.conflux.web.controller.privateKey.domain.PrivateKey;
import com.conflux.web.controller.privateKey.service.IPrivateKeyService;
import com.conflux.common.utils.poi.ExcelUtil;
import com.conflux.common.core.page.TableDataInfo;
/**
* 私钥申请Controller
*
* @author conflux
* @date 2022-06-07
*/
@RestController
@RequestMapping("/conflux/key")
public class PrivateKeyController extends BaseController
{
@Autowired
private IPrivateKeyService privateKeyService;
/**
* 查询私钥申请列表
*/
@PreAuthorize("@ss.hasPermi('system:key:list')")
@GetMapping("/list")
public TableDataInfo list(PrivateKey privateKey)
{
startPage();
List<PrivateKey> list = privateKeyService.selectPrivateKeyList(privateKey);
return getDataTable(list);
}
/**
* 导出私钥申请列表
*/
@PreAuthorize("@ss.hasPermi('system:key:export')")
@Log(title = "私钥申请", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(HttpServletResponse response, PrivateKey privateKey)
{
List<PrivateKey> list = privateKeyService.selectPrivateKeyList(privateKey);
ExcelUtil<PrivateKey> util = new ExcelUtil<PrivateKey>(PrivateKey.class);
util.exportExcel(response, list, "私钥申请数据");
}
/**
* 获取私钥申请详细信息
*/
@PreAuthorize("@ss.hasPermi('system:key:query')")
@GetMapping(value = "/{id}")
public AjaxResult getInfo(@PathVariable("id") Long id)
{
return AjaxResult.success(privateKeyService.selectPrivateKeyById(id));
}
/**
* 新增私钥申请
*/
@PreAuthorize("@ss.hasPermi('system:key:add')")
@Log(title = "私钥申请", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@RequestBody PrivateKey privateKey)
{
return toAjax(privateKeyService.insertPrivateKey(privateKey));
}
/**
* 修改私钥申请
*/
@PreAuthorize("@ss.hasPermi('system:key:edit')")
@Log(title = "私钥申请", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@RequestBody PrivateKey privateKey)
{
return toAjax(privateKeyService.updatePrivateKey(privateKey));
}
/**
* 删除私钥申请
*/
@PreAuthorize("@ss.hasPermi('system:key:remove')")
@Log(title = "私钥申请", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public AjaxResult remove(@PathVariable Long[] ids)
{
return toAjax(privateKeyService.deletePrivateKeyByIds(ids));
}
}

37
conflux-admin/src/main/java/com/conflux/web/controller/privateKey/domain/PrivateKey.java

@ -0,0 +1,37 @@
package com.conflux.web.controller.privateKey.domain;
import com.conflux.common.annotation.Excel;
import com.conflux.common.core.domain.BaseEntity;
import lombok.Data;
/**
* 私钥申请对象 private_key
*
* @author conflux
* @date 2022-06-07
*/
@Data
public class PrivateKey extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** */
private Long id;
/** 项目名称 */
@Excel(name = "项目名称")
private String unitName;
/** appid */
@Excel(name = "appid")
private String appId;
/** 私钥 */
@Excel(name = "私钥")
private String privateKey;
/** 0正常1禁用 */
@Excel(name = "0正常1禁用")
private String stauts;
}

68
conflux-admin/src/main/java/com/conflux/web/controller/privateKey/mapper/PrivateKeyMapper.java

@ -0,0 +1,68 @@
package com.conflux.web.controller.privateKey.mapper;
import java.util.List;
import com.conflux.web.controller.privateKey.domain.PrivateKey;
/**
* 私钥申请Mapper接口
*
* @author conflux
* @date 2022-06-07
*/
public interface PrivateKeyMapper
{
/**
* 查询私钥申请
*
* @param id 私钥申请主键
* @return 私钥申请
*/
public PrivateKey selectPrivateKeyById(Long id);
/**
* 通过appid查询
* @param appId
* @return
*/
public PrivateKey selectPrivateKeyByAppId(String appId);
/**
* 查询私钥申请列表
*
* @param privateKey 私钥申请
* @return 私钥申请集合
*/
public List<PrivateKey> selectPrivateKeyList(PrivateKey privateKey);
/**
* 新增私钥申请
*
* @param privateKey 私钥申请
* @return 结果
*/
public int insertPrivateKey(PrivateKey privateKey);
/**
* 修改私钥申请
*
* @param privateKey 私钥申请
* @return 结果
*/
public int updatePrivateKey(PrivateKey privateKey);
/**
* 删除私钥申请
*
* @param id 私钥申请主键
* @return 结果
*/
public int deletePrivateKeyById(Long id);
/**
* 批量删除私钥申请
*
* @param ids 需要删除的数据主键集合
* @return 结果
*/
public int deletePrivateKeyByIds(Long[] ids);
}

67
conflux-admin/src/main/java/com/conflux/web/controller/privateKey/service/IPrivateKeyService.java

@ -0,0 +1,67 @@
package com.conflux.web.controller.privateKey.service;
import java.util.List;
import com.conflux.web.controller.privateKey.domain.PrivateKey;
/**
* 私钥申请Service接口
*
* @author conflux
* @date 2022-06-07
*/
public interface IPrivateKeyService
{
/**
* 查询私钥申请
*
* @param id 私钥申请主键
* @return 私钥申请
*/
public PrivateKey selectPrivateKeyById(Long id);
/**
* 通过appid查询
* @param appId
* @return
*/
public PrivateKey selectPrivateKeyByAppId(String appId);
/**
* 查询私钥申请列表
*
* @param privateKey 私钥申请
* @return 私钥申请集合
*/
public List<PrivateKey> selectPrivateKeyList(PrivateKey privateKey);
/**
* 新增私钥申请
*
* @param privateKey 私钥申请
* @return 结果
*/
public int insertPrivateKey(PrivateKey privateKey);
/**
* 修改私钥申请
*
* @param privateKey 私钥申请
* @return 结果
*/
public int updatePrivateKey(PrivateKey privateKey);
/**
* 批量删除私钥申请
*
* @param ids 需要删除的私钥申请主键集合
* @return 结果
*/
public int deletePrivateKeyByIds(Long[] ids);
/**
* 删除私钥申请信息
*
* @param id 私钥申请主键
* @return 结果
*/
public int deletePrivateKeyById(Long id);
}

156
conflux-admin/src/main/java/com/conflux/web/controller/privateKey/service/impl/PrivateKeyServiceImpl.java

@ -0,0 +1,156 @@
package com.conflux.web.controller.privateKey.service.impl;
import java.math.BigInteger;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import com.conflux.common.utils.DateUtils;
import com.conflux.common.utils.uuid.IdUtils;
import com.conflux.web.controller.nft.domain.ConfluxArt;
import com.conflux.web.controller.util.AESUtil;
import com.conflux.web.controller.util.redis.RedisUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import com.conflux.web.controller.privateKey.mapper.PrivateKeyMapper;
import com.conflux.web.controller.privateKey.domain.PrivateKey;
import com.conflux.web.controller.privateKey.service.IPrivateKeyService;
import javax.annotation.Resource;
/**
* 私钥申请Service业务层处理
*
* @author conflux
* @date 2022-06-07
*/
@Service
public class PrivateKeyServiceImpl implements IPrivateKeyService
{
@Autowired
private PrivateKeyMapper privateKeyMapper;
@Resource
private RedisUtils redisUtils;
@Resource
RedisTemplate redisTemplate;
/**
* 查询私钥申请
*
* @param id 私钥申请主键
* @return 私钥申请
*/
@Override
public PrivateKey selectPrivateKeyById(Long id)
{
return privateKeyMapper.selectPrivateKeyById(id);
}
@Override
public PrivateKey selectPrivateKeyByAppId(String appId) {
return privateKeyMapper.selectPrivateKeyByAppId(appId);
}
/**
* 查询私钥申请列表
*
* @param privateKey 私钥申请
* @return 私钥申请
*/
@Override
public List<PrivateKey> selectPrivateKeyList(PrivateKey privateKey)
{
return privateKeyMapper.selectPrivateKeyList(privateKey);
}
/**
* 新增私钥申请
*
* @param privateKey 私钥申请
* @return 结果
*/
@Override
public int insertPrivateKey(PrivateKey privateKey) {
privateKey.setCreateTime(DateUtils.getNowDate());
String fastUUID = IdUtils.fastUUID();
String appid = null;
String key= null;
try {
appid =generateOrderSn();
key = AESUtil.encrypt(fastUUID, ConfluxArt.AESKEY);
} catch (Exception e) {
e.printStackTrace();
}
privateKey.setAppId(appid);
privateKey.setPrivateKey(key.toLowerCase());
return privateKeyMapper.insertPrivateKey(privateKey);
}
/**
* 修改私钥申请
*
* @param privateKey 私钥申请
* @return 结果
*/
@Override
public int updatePrivateKey(PrivateKey privateKey)
{
return privateKeyMapper.updatePrivateKey(privateKey);
}
/**
* 批量删除私钥申请
*
* @param ids 需要删除的私钥申请主键
* @return 结果
*/
@Override
public int deletePrivateKeyByIds(Long[] ids)
{
return privateKeyMapper.deletePrivateKeyByIds(ids);
}
/**
* 删除私钥申请信息
*
* @param id 私钥申请主键
* @return 结果
*/
@Override
public int deletePrivateKeyById(Long id)
{
return privateKeyMapper.deletePrivateKeyById(id);
}
/**
* 生成appid
* @return
*/
public String generateOrderSn() {
StringBuilder sb = new StringBuilder();
String date = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date());
// 拼接key值
String key = "UUID:"+ date;
int code = (int)(Math.random() * (40000 -10000)) + 10000;
Long increment = incr(key, code);
sb.append(date);
sb.append(String.format("%02d", 2));
sb.append(String.format("%02d",2));
String incrementStr = increment.toString();
if (incrementStr.length() <= 6) {
sb.append(String.format("%06d", increment));
} else {
sb.append(incrementStr);
}
return sb.toString();
}
/***
* 按delta递增
* @param key
* @param delta
* @return
*/
public Long incr(String key, long delta) {
return redisTemplate.opsForValue().increment(key, delta);
}
}

50
conflux-admin/src/main/java/com/conflux/web/controller/util/AESUtil.java

@ -1,6 +1,8 @@
package com.conflux.web.controller.util;
import com.conflux.common.utils.sign.Md5Utils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
@ -172,11 +174,55 @@ public final class AESUtil {
}
return result;
}
// 加密
public static String Encrypt(String sSrc, String sKey) throws Exception {
if (sKey == null) {
System.out.print("Key为空null");
return null;
}
byte[] raw = sKey.getBytes("utf-8");
SecretKeySpec keySpec = new SecretKeySpec(raw, "AES");
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");//"算法/模式/补码方式"cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
cipher.init(Cipher.ENCRYPT_MODE, keySpec);
byte[] encrypted = cipher.doFinal(sSrc.getBytes("utf-8"));
return new String(Base64.encodeBase64(encrypted));//此处使用BASE64做转码功能,同时能起到2次加密的作用。
}
// 解密
public static String Decrypt(String sSrc, String sKey) throws Exception {
try {
// 判断Key是否正确
if (sKey == null) {
System.out.print("Key为空null");
return null;
}
byte[] raw = sKey.getBytes("utf-8");
SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
Cipher cipher =Cipher.getInstance("AES/ECB/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, skeySpec);
byte[] encrypted1 = Base64.decodeBase64(sSrc.getBytes());//先用base64解密
try {
byte[] original = cipher.doFinal(encrypted1);
String originalString = new String(original, "utf-8");
return originalString;
} catch (Exception e) {
return null;
}
} catch (Exception ex) {
System.out.println(ex.toString());
return null;
}
}
public static void main(String[] args) {
try {
String encrypt = encrypt("8cfd5c44-2efd-4061-bcf3-4d51e623b69f","CONFLUX@123");
System.err.println(encrypt);
//AES
String encrypt = Encrypt("56241DA2A04C2D8BAEDFF600976B5FFE4BF4910A52DC139D9F77521FFD1D28CB220E079108CCEE934D5654D2901DF44AFAE3B80664AD25E86ACD750805C35507200240EA65ED1190E15FA76FBB853D56","CONFLUX@12345678");
System.err.println(encrypt);
//md5
// String hash = Md5Utils.md5Salt("d2f95f5f15389bd508765957f8543bc48b8e28cdfcde059a41421c2e17336f10fa475bba8c50963d4a28f697b559fa8d");
// System.err.println(hash);
} catch (Exception e) {
e.printStackTrace();
}

194
conflux-admin/src/main/java/com/conflux/web/controller/util/ScheduledTask.java

@ -0,0 +1,194 @@
package com.conflux.web.controller.util;
import cn.hutool.core.date.DateUtil;
import com.conflux.web.controller.collect.domain.CollectConfig;
import com.conflux.web.controller.collect.service.ICollectConfigService;
import com.conflux.web.controller.nft.domain.EventParam;
import com.conflux.web.controller.nft.domain.vo.FilterMapVO;
import com.conflux.web.controller.nft.service.IHandlerStrategy;
import com.google.gson.Gson;
import conflux.web3j.Cfx;
import conflux.web3j.Request;
import conflux.web3j.request.Epoch;
import conflux.web3j.request.LogFilter;
import conflux.web3j.response.Log;
import conflux.web3j.types.Address;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.Scheduled;
import javax.annotation.Resource;
import java.math.BigInteger;
import java.util.*;
import java.util.stream.Collectors;
/**
* @Author _007long
* @Date 2022 06 07
**/
@Slf4j
@Configuration
public class ScheduledTask {
@Value("${conflux.contract}")
private String contract;
@Resource
private ICollectConfigService collectConfigService;
@Resource
private IHandlerStrategy iHandlerStrategy;
private Map<String,CollectConfig> map=new HashMap();
//@Scheduled(fixedDelay = 5000L)
public void executeMakeUp() {
CollectConfig collect = collectConfigService.selectCollectConfigByStatus();
if (collect.getOnPause()) {
log.info("[dispatchHandler]{}", "暂停中");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return;
}
//=======检查数据=======
List<EventParam> eventParams = new ArrayList<>();
EventParam eventParam = new EventParam();
eventParam.setChainId(collect.getChainId());
eventParam.setContract(contract);//合约
eventParam.setParam("address,address,uint256");
eventParam.setMethod("Transfer");
eventParam.setType(20000);
eventParam.setRemark("Wu jing");
eventParams.add(eventParam);
if (CollectionUtils.isEmpty(eventParams)) {
log.error("[dispatchHandler]{}", "没有需要监听的数据");
return;
}
Gson gson = new Gson();
//获取event,使用 webService
//记录数据
Cfx cfx = null;
try {
cfx = Cfx.create(collect.getNode(), 3, 1000);
} catch (Exception e) {
e.printStackTrace();
return;
}
FilterMapVO vo = getFilter(eventParams);
CollectConfig collectConfig = map.get(contract);
long from = 0l;
if (null != collectConfig) {
from = collectConfig.getEpochNumber();
} else {
from = collect.getEpochNumber();
}
// Invoke cfx method
BigInteger epoch = cfx.getEpochNumber().sendAndGet();
log.info("[executeMakeUp][Current epoch]:{}", epoch);
long to = epoch.intValue() - 5;
if (to - from > collect.getLimitCount()) {
to = from + collect.getLimitCount();
}
vo.getLogFilter().setFromEpoch(Epoch.numberOf(from));
//当前高度
vo.getLogFilter().setToEpoch(Epoch.numberOf(to));
Request<List<Log>, Log.Response> events = cfx.getLogs(vo.getLogFilter());
try {
events = cfx.getLogs(vo.getLogFilter());
} catch (Exception e) {
e.printStackTrace();
}
if (events == null) {
log.info("[executeMakeUp][请重启服务]");
return;
}
List<Log> logList = events.sendAndGet();
boolean isSuccess = false;
if (CollectionUtils.isEmpty(logList)) {
log.info("[executeMakeUp][此区间暂无日志]:from:{} to:{}", from, to);
isSuccess = true;
}
for (Log l : logList) {
//处理高度信息
String evAddress = l.getTopics().get(0);
String tokenAddress = l.getAddress().getAddress();
if (tokenAddress.contains("TYPE")) {
Address a = new Address(tokenAddress);
tokenAddress = a.getAddress();
}
int type = vo.getMap().get(evAddress + "-" + tokenAddress.toLowerCase());
if (type == 0) {
log.info("[dispatchHandler][暂无符合条件的数据]");
return;
}
boolean res;
try {
res = iHandlerStrategy.relayHandler(cfx, gson.toJson(l), type);
} catch (Exception e) {
e.printStackTrace();
isSuccess = false;
log.info("[dispatchHandler][数据错误未分配]{}", l.getData());
break;
}
if (res) {
log.info("[dispatchHandler][分配成功]{}", evAddress);
isSuccess = true;
} else {
log.info("[dispatchHandler][数据错误未分配]{}", l.getData());
isSuccess = false;
break;
}
}
//分析数据拉取成功
CollectConfig t = new CollectConfig();
t.setId(collect.getId());
t.setUpdateTime(DateUtil.currentSeconds());
if (isSuccess) {
t.setEpochNumber(to);
log.info("[dispatchHandler][更新高度]:{}", to);
map.put(contract,t);
}
}
/**
* 每隔一分钟更新一次数据
*/
//@Scheduled(fixedDelay = 60000L)
public void flushDiskToMysql(){
CollectConfig collectConfig = map.get(contract);
if (null!=collectConfig){
//写入数据库
collectConfigService.updateCollectConfig(collectConfig);
System.err.println(map.toString());
}else {
System.err.println("写入数据库失败!");
}
}
private FilterMapVO getFilter(List<EventParam> eventParams) {
// PubSub Subscribe to incoming events and process incoming events
LogFilter filter = new LogFilter();
//添加监听合约:
List<Address> moList = eventParams.stream().map(
eventParam -> new Address(eventParam.getContract())).collect(Collectors.toList());
filter.setAddress(moList);
//添加监听方法
List<String> list = new ArrayList<>();
//Transfer
Map<String, Integer> map = new HashMap<>(eventParams.size());
eventParams.forEach(eventParam -> {
String evAddress = CfxUtils.getEventKeccak(eventParam.getMethod(), Arrays.asList(eventParam.getParam().split(",")));
// log.info("token:{} method:{} kec:{}", eventParam.getContract(), eventParam.getMethod(), evAddress);
map.put(evAddress + "-" + eventParam.getContract().toLowerCase(), eventParam.getType());
list.add(evAddress);
});
List<List<String>> lists = new ArrayList<>();
lists.add(list);
filter.setTopics(lists);
FilterMapVO vo = new FilterMapVO();
vo.setLogFilter(filter);
vo.setMap(map);
return vo;
}
}

9
conflux-admin/src/main/resources/application-druid.yml

@ -54,4 +54,11 @@ spring:
merge-sql: true
wall:
config:
multi-statement-allow: true
multi-statement-allow: true
conflux:
#合约
contract: cfxtest:accv8tzc61p5b9r2nwjpy36u2msea4e95u40zzxn8j
# 执行地址
owner: cfxtest:aarr1hw0tab9sb4jxyu3g2v7xzknbkpn72p1uxp3uz
###私钥位置
privateKey: E862

9
conflux-admin/src/main/resources/application-prod.yml

@ -54,4 +54,11 @@ spring:
merge-sql: true
wall:
config:
multi-statement-allow: true
multi-statement-allow: true
conflux:
#合约
contract: cfxtest:accv8tzc61p5b9r2nwjpy36u2msea4e95u40zzxn8j
# 执行地址
owner: cfxtest:aarr1hw0tab9sb4jxyu3g2v7xzknbkpn72p1uxp3uz
###私钥位置
privateKey: E862

1
conflux-admin/src/main/resources/application.yml

@ -121,3 +121,4 @@ xss:
excludes: /system/notice
# 匹配链接
urlPatterns: /system/*,/monitor/*,/tool/*

64
conflux-common/src/main/java/com/conflux/common/utils/sign/Md5Utils.java

@ -2,6 +2,8 @@ package com.conflux.common.utils.sign;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import org.apache.commons.codec.digest.DigestUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -13,24 +15,8 @@ import org.slf4j.LoggerFactory;
public class Md5Utils
{
private static final Logger log = LoggerFactory.getLogger(Md5Utils.class);
public static final String SALT="7a8b9c10d12e13f";
private static byte[] md5(String s)
{
MessageDigest algorithm;
try
{
algorithm = MessageDigest.getInstance("MD5");
algorithm.reset();
algorithm.update(s.getBytes("UTF-8"));
byte[] messageDigest = algorithm.digest();
return messageDigest;
}
catch (Exception e)
{
log.error("MD5 Error...", e);
}
return null;
}
private static final String toHex(byte hash[])
{
@ -52,16 +38,38 @@ public class Md5Utils
return buf.toString();
}
public static String hash(String s)
{
try
{
return new String(toHex(md5(s)).getBytes(StandardCharsets.UTF_8), StandardCharsets.UTF_8);
}
catch (Exception e)
{
log.error("not supported charset...{}", e);
return s;
}
public static String md5(String src){
return DigestUtils.md5Hex(src);
}
/**
* 1次加密: 明文+随机Salt
* @param inputPass
* @return
*/
public static String md5Salt(String inputPass){
String str = "" +SALT.charAt(0) + SALT.charAt(2) + inputPass + SALT.charAt(5) + SALT.charAt(4);
return md5(str);
}
/**
* 2次加密: 用户输入+随机Salt
* @param formPass
* @param salt
* @return
*/
public static String md5SecondSalt (String formPass,String salt){
String str = "" +salt.charAt(0) + salt.charAt(2) + formPass + salt.charAt(5) + salt.charAt(4);
return md5(str);
}
/**
*
* @param inputPass
* @param salt
* @return
*/
public static String md5Last(String inputPass,String salt){
String fromPass = md5Salt(inputPass);
String dbPass = md5SecondSalt(fromPass, salt);
return dbPass;
}
}

43
conflux-system/src/main/resources/mapper/system/ContractConfigMapper.xml

@ -5,27 +5,32 @@
<mapper namespace="com.conflux.web.controller.contract.mapper.ContractConfigMapper">
<resultMap type="ContractConfig" id="ContractConfigResult">
<result property="id" column="id"/>
<result property="unitName" column="unit_name"/>
<result property="contract" column="contract"/>
<result property="owner" column="owner"/>
<result property="gasPrice" column="gas_price"/>
<result property="privateKey" column="private_key"/>
<result property="createTime" column="create_time"/>
<result property="updateTime" column="update_time"/>
<result property="id" column="id" />
<result property="unitName" column="unit_name" />
<result property="contract" column="contract" />
<result property="owner" column="owner" />
<result property="gasPrice" column="gas_price" />
<result property="privateKey" column="private_key" />
<result property="threshold" column="threshold" />
<result property="totalThreshold" column="total_threshold" />
<result property="createTime" column="create_time" />
<result property="updateTime" column="update_time" />
</resultMap>
<sql id="selectContractConfigVo">
select id, unit_name,contract, owner,gas_price, private_key, create_time, update_time
from contract_config
select id, unit_name, contract, owner, gas_price, private_key, threshold, total_threshold, create_time, update_time from contract_config
</sql>
<select id="selectContractConfigList" parameterType="ContractConfig" resultMap="ContractConfigResult">
<include refid="selectContractConfigVo"/>
<where>
<if test="contract != null and contract != ''">and contract = #{contract}</if>
<if test="owner != null and owner != ''">and owner = #{owner}</if>
<if test="privateKey != null and privateKey != ''">and private_key = #{privateKey}</if>
<if test="unitName != null and unitName != ''"> and unit_name like concat('%', #{unitName}, '%')</if>
<if test="contract != null and contract != ''"> and contract = #{contract}</if>
<if test="owner != null and owner != ''"> and owner = #{owner}</if>
<if test="gasPrice != null "> and gas_price = #{gasPrice}</if>
<if test="privateKey != null and privateKey != ''"> and private_key = #{privateKey}</if>
<if test="threshold != null "> and threshold = #{threshold}</if>
<if test="totalThreshold != null "> and total_threshold = #{totalThreshold}</if>
</where>
</select>
@ -45,8 +50,10 @@
<if test="unitName != null">unit_name,</if>
<if test="contract != null">contract,</if>
<if test="owner != null">owner,</if>
<if test="privateKey != null">private_key,</if>
<if test="gasPrice != null">gas_price,</if>
<if test="privateKey != null">private_key,</if>
<if test="threshold != null">threshold,</if>
<if test="totalThreshold != null">total_threshold,</if>
<if test="createTime != null">create_time,</if>
<if test="updateTime != null">update_time,</if>
</trim>
@ -54,8 +61,10 @@
<if test="unitName != null">#{unitName},</if>
<if test="contract != null">#{contract},</if>
<if test="owner != null">#{owner},</if>
<if test="privateKey != null">#{privateKey},</if>
<if test="gasPrice != null">#{gasPrice},</if>
<if test="privateKey != null">#{privateKey},</if>
<if test="threshold != null">#{threshold},</if>
<if test="totalThreshold != null">#{totalThreshold},</if>
<if test="createTime != null">#{createTime},</if>
<if test="updateTime != null">#{updateTime},</if>
</trim>
@ -67,8 +76,10 @@
<if test="unitName != null">unit_name = #{unitName},</if>
<if test="contract != null">contract = #{contract},</if>
<if test="owner != null">owner = #{owner},</if>
<if test="privateKey != null">private_key = #{privateKey},</if>
<if test="gasPrice != null">gas_price = #{gasPrice},</if>
<if test="privateKey != null">private_key = #{privateKey},</if>
<if test="threshold != null">threshold = #{threshold},</if>
<if test="totalThreshold != null">total_threshold = #{totalThreshold},</if>
<if test="createTime != null">create_time = #{createTime},</if>
<if test="updateTime != null">update_time = #{updateTime},</if>
</trim>

5
conflux-system/src/main/resources/mapper/system/NftLogMapper.xml

@ -27,7 +27,10 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<include refid="selectNftLogVo"/>
where id = #{id}
</select>
<select id="selectSum" resultType="java.lang.Integer">
SELECT SUM(nft_num) FROM `nft_log` WHERE unit_name=#{unitName}
</select>
<insert id="insertNftLog" parameterType="NftLog" useGeneratedKeys="true" keyProperty="id">
insert into nft_log
<trim prefix="(" suffix=")" suffixOverrides=",">

79
conflux-system/src/main/resources/mapper/system/PrivateKeyMapper.xml

@ -0,0 +1,79 @@
<?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.conflux.web.controller.privateKey.mapper.PrivateKeyMapper">
<resultMap type="PrivateKey" id="PrivateKeyResult">
<result property="id" column="id" />
<result property="unitName" column="unit_name" />
<result property="appId" column="app_id" />
<result property="privateKey" column="private_key" />
<result property="stauts" column="stauts" />
<result property="createTime" column="create_time" />
</resultMap>
<sql id="selectPrivateKeyVo">
select id, unit_name, app_id, private_key, stauts, create_time from private_key
</sql>
<select id="selectPrivateKeyList" parameterType="PrivateKey" resultMap="PrivateKeyResult">
<include refid="selectPrivateKeyVo"/>
<where>
<if test="unitName != null and unitName != ''"> and unit_name like concat('%', #{unitName}, '%')</if>
<if test="appId != null and appId != ''"> and app_id = #{appId}</if>
<if test="privateKey != null and privateKey != ''"> and private_key = #{privateKey}</if>
<if test="stauts != null and stauts != ''"> and stauts = #{stauts}</if>
</where>
</select>
<select id="selectPrivateKeyById" parameterType="Long" resultMap="PrivateKeyResult">
<include refid="selectPrivateKeyVo"/>
where id = #{id}
</select>
<select id="selectPrivateKeyByAppId" parameterType="String" resultMap="PrivateKeyResult">
<include refid="selectPrivateKeyVo"/>
where app_id = #{appId}
</select>
<insert id="insertPrivateKey" parameterType="PrivateKey" useGeneratedKeys="true" keyProperty="id">
insert into private_key
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="unitName != null">unit_name,</if>
<if test="appId != null">app_id,</if>
<if test="privateKey != null">private_key,</if>
<if test="stauts != null">stauts,</if>
<if test="createTime != null">create_time,</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="unitName != null">#{unitName},</if>
<if test="appId != null">#{appId},</if>
<if test="privateKey != null">#{privateKey},</if>
<if test="stauts != null">#{stauts},</if>
<if test="createTime != null">#{createTime},</if>
</trim>
</insert>
<update id="updatePrivateKey" parameterType="PrivateKey">
update private_key
<trim prefix="SET" suffixOverrides=",">
<if test="unitName != null">unit_name = #{unitName},</if>
<if test="appId != null">app_id = #{appId},</if>
<if test="privateKey != null">private_key = #{privateKey},</if>
<if test="stauts != null">stauts = #{stauts},</if>
<if test="createTime != null">create_time = #{createTime},</if>
</trim>
where id = #{id}
</update>
<delete id="deletePrivateKeyById" parameterType="Long">
delete from private_key where id = #{id}
</delete>
<delete id="deletePrivateKeyByIds" parameterType="String">
delete from private_key where id in
<foreach item="id" collection="array" open="(" separator="," close=")">
#{id}
</foreach>
</delete>
</mapper>
Loading…
Cancel
Save