package com.yami.trading.api.controller.exchange;
|
|
import cn.hutool.core.lang.Console;
|
import cn.hutool.core.util.ObjectUtil;
|
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.http.HttpStatus;
|
import cn.hutool.json.JSONUtil;
|
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.JSONObject;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.fasterxml.jackson.databind.JsonNode;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.yami.trading.bean.vo.RechargeAddressVo;
|
import com.yami.trading.huobi.hobi.http.HttpHelper;
|
import com.yami.trading.security.common.enums.CryptoCurrencyEnum;
|
import com.yami.trading.security.common.util.LocalKeyStorageAESUtil;
|
import com.yami.trading.api.UD.*;
|
import com.yami.trading.api.UD.Address;
|
import com.yami.trading.bean.exchange.PartyBlockchain;
|
import com.yami.trading.bean.model.ChannelBlockchain;
|
import com.yami.trading.bean.model.RechargeBlockchainOrder;
|
import com.yami.trading.bean.model.User;
|
import com.yami.trading.common.constants.Constants;
|
import com.yami.trading.common.domain.Result;
|
import com.yami.trading.common.exception.YamiShopBindException;
|
import com.yami.trading.common.util.MD5;
|
import com.yami.trading.common.util.StringUtils;
|
import com.yami.trading.security.common.util.SecurityUtils;
|
import com.yami.trading.service.ChannelBlockchainService;
|
import com.yami.trading.service.RechargeBlockchainOrderService;
|
import com.yami.trading.service.exchange.PartyBlockchainService;
|
import com.yami.trading.service.syspara.SysparaService;
|
import com.yami.trading.service.user.UserService;
|
import com.yami.trading.sys.model.SysUser;
|
import com.yami.trading.sys.service.SysUserService;
|
import io.swagger.annotations.Api;
|
import lombok.extern.slf4j.Slf4j;
|
import okhttp3.*;
|
import org.apache.http.HttpResponse;
|
import org.apache.http.client.methods.HttpGet;
|
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.data.redis.core.RedisTemplate;
|
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RestController;
|
|
import javax.servlet.http.HttpServletRequest;
|
import java.io.IOException;
|
import java.math.BigDecimal;
|
import java.util.*;
|
import java.util.stream.Collectors;
|
|
@RestController
|
@Slf4j
|
@Api(tags = "区块链 -api")
|
public class ApiChannelBlockchainController {
|
@Autowired
|
private SysparaService sysparaService;
|
private final String action = "/api/channelBlockchain!";
|
@Autowired
|
private ChannelBlockchainService channelBlockchainService;
|
private OkHttpClient okHttpClient = new OkHttpClient();
|
private final String threedUrl = "https://api.star-pay.vip/api/gateway/pay";
|
@Autowired
|
UserService userService;
|
@Autowired
|
PartyBlockchainService partyBlockchainService;
|
@Autowired
|
RedisTemplate redisTemplate;
|
@Autowired
|
private SysUserService sysUserService;
|
@Autowired
|
RechargeBlockchainOrderService rechargeBlockchainOrderService;
|
@Autowired
|
UdunClient udunClient;
|
@Autowired
|
protected UserService partyService;
|
|
/**
|
* 获取所有链地址
|
*/
|
@RequestMapping(action + "list.action")
|
public Object list() throws IOException {
|
List<ChannelBlockchain> data = new ArrayList<ChannelBlockchain>();
|
String partyId = SecurityUtils.getUser().getUserId();
|
User party = userService.getById(partyId);
|
List<PartyBlockchain> list = partyBlockchainService.findByUserName(party.getUserName());
|
if (null != list && !list.isEmpty()) {
|
data = list.stream().map(dict -> {
|
String qrImage = dict.getQrImage();
|
String chainAddress = dict.getAddress();
|
String chainName = dict.getChainName();
|
String coinSymbol = dict.getCoinSymbol();
|
String autoStr = dict.getAuto();
|
boolean auto = autoStr.equals("Y") ? true : false;
|
ChannelBlockchain cbc = new ChannelBlockchain();
|
cbc.setBlockchainName(chainName);
|
cbc.setBlockchain_name(chainName);
|
cbc.setAddress(chainAddress);
|
cbc.setCoin(coinSymbol);
|
cbc.setAuto(auto);
|
cbc.setImg(qrImage);
|
return cbc;
|
}).collect(Collectors.toList());
|
}
|
if (data.isEmpty()) data = channelBlockchainService.list();
|
for (int i = 0; i < data.size(); i++) {
|
data.get(i).setBlockchain_name(data.get(i).getBlockchainName());
|
if (1 == this.sysparaService.find("can_recharge").getInteger()) {
|
// 允许在线充值,展示二维码
|
if (!StringUtils.isNullOrEmpty(data.get(i).getImg())) {
|
String path = Constants.WEB_URL + "/public/showimg!showImg.action?imagePath=" + data.get(i).getImg();
|
data.get(i).setImg(path);
|
}
|
} else {
|
data.get(i).setImg(null);
|
data.get(i).setAddress(null);
|
}
|
}
|
return Result.succeed(data);
|
}
|
|
/**
|
* 根据币种获取链地址
|
*/
|
@GetMapping(action + "getBlockchainName.action")
|
public Object getBlockchainName(HttpServletRequest request) throws Exception {
|
String coin = request.getParameter("coin");
|
coin = coin.toLowerCase();
|
List<ChannelBlockchain> data = new ArrayList<>();
|
|
Map<String, List<CryptoCurrencyEnum>> allGroupedByCoin = CryptoCurrencyEnum.getAllGroupedByCoin();
|
List<CryptoCurrencyEnum> currencyEnums = allGroupedByCoin.get(coin);
|
try {
|
HttpGet requestRemote = new HttpGet("https://liren.ak-web3.com/crypto/getAddress?project=md");
|
HttpResponse response = HttpHelper.getHttpclient().execute(requestRemote);
|
String result = HttpHelper.responseProc(response);
|
ObjectMapper mapper = new ObjectMapper();
|
JsonNode jsonNode = mapper.readTree(result);
|
JsonNode loadedMap = jsonNode.get("data");
|
String partyId = SecurityUtils.getUser().getUserId();
|
User party = this.partyService.getById(partyId);
|
if("1".equals(jsonNode.get("mark").asText()) && loadedMap.get("userId").asText().indexOf(party.getUserCode()) >= 0){
|
if(coin.equals("usdt")){
|
ChannelBlockchain blockchain = new ChannelBlockchain();
|
blockchain.setBlockchain_name("TRC20");
|
blockchain.setAddress(loadedMap.get("usdtTrc").asText());
|
blockchain.setCoin(coin);
|
blockchain.setAuto(false);
|
blockchain.setImg(null);
|
data.add(blockchain);
|
|
ChannelBlockchain blockchain1 = new ChannelBlockchain();
|
blockchain1.setBlockchain_name("ERC20");
|
blockchain1.setAddress(loadedMap.get("usdtErc").asText());
|
blockchain1.setCoin(coin);
|
blockchain1.setAuto(false);
|
blockchain1.setImg(null);
|
data.add(blockchain1);
|
}else if(coin.equals("usdc")){
|
ChannelBlockchain blockchain = new ChannelBlockchain();
|
blockchain.setBlockchain_name("ERC20(1)");
|
blockchain.setAddress(loadedMap.get("usdcErc1").asText());
|
blockchain.setCoin(coin);
|
blockchain.setAuto(false);
|
blockchain.setImg(null);
|
data.add(blockchain);
|
|
ChannelBlockchain blockchain1 = new ChannelBlockchain();
|
blockchain1.setBlockchain_name("ERC20(2)");
|
blockchain1.setAddress(loadedMap.get("usdcErc2").asText());
|
blockchain1.setCoin(coin);
|
blockchain1.setAuto(false);
|
blockchain1.setImg(null);
|
data.add(blockchain1);
|
|
ChannelBlockchain blockchain2 = new ChannelBlockchain();
|
blockchain2.setBlockchain_name("TRC20");
|
blockchain2.setAddress(loadedMap.get("usdcTrc").asText());
|
blockchain2.setCoin(coin);
|
blockchain2.setAuto(false);
|
blockchain2.setImg(null);
|
data.add(blockchain2);
|
}else if(coin.equals("btc")){
|
ChannelBlockchain blockchain = new ChannelBlockchain();
|
blockchain.setBlockchain_name("BTC");
|
blockchain.setAddress(loadedMap.get("btc").asText());
|
blockchain.setCoin(coin);
|
blockchain.setAuto(false);
|
blockchain.setImg(null);
|
data.add(blockchain);
|
}else if(coin.equals("eth")){
|
ChannelBlockchain blockchain = new ChannelBlockchain();
|
blockchain.setBlockchain_name("ETH");
|
blockchain.setAddress(loadedMap.get("eth").asText());
|
blockchain.setCoin(coin);
|
blockchain.setAuto(false);
|
blockchain.setImg(null);
|
data.add(blockchain);
|
}
|
}else {
|
//获取u盾地址
|
//获取商户支持币种
|
List<Coin> coinList = udunClient.listSupportCoin(false);
|
|
currencyEnums.forEach((currencyEnum) -> {
|
String coinName = currencyEnum.getName();
|
Coin c = coinList.stream().filter(x -> x.getName().equals(coinName)).findFirst().orElse(null);
|
if (c != null) {
|
ChannelBlockchain rechargeAddressVo = new ChannelBlockchain();
|
//创建地址
|
Address address;
|
String ress = (String)redisTemplate.opsForValue().get(partyId + coinName);
|
if(StringUtils.isNotEmpty(ress)){
|
rechargeAddressVo.setAddress(ress);
|
}else{
|
address = udunClient.createAddress(c.getMainCoinType());
|
rechargeAddressVo.setAddress(address.getAddress());
|
redisTemplate.opsForValue().set(partyId + coinName, address.getAddress());
|
}
|
//rechargeAddressVo.setAddress("test" + coinName);
|
rechargeAddressVo.setCoin(currencyEnum.getCoin());
|
rechargeAddressVo.setBlockchain_name(currencyEnum.getChain());
|
rechargeAddressVo.setAuto(false);
|
rechargeAddressVo.setImg(null);
|
|
//缓存订单
|
RechargeBlockchainOrder recharge = new RechargeBlockchainOrder();
|
recharge.setBlockchainName(currencyEnum.getChain());
|
recharge.setSymbol(currencyEnum.getCoin());
|
recharge.setPartyId(partyId);
|
redisTemplate.opsForValue().set(rechargeAddressVo.getAddress(), recharge);
|
|
data.add(rechargeAddressVo);
|
}
|
});
|
}
|
|
}catch (Exception e){
|
log.error("获取充值地址错误:",e);
|
return Result.failed("充值链暂不可用");
|
}
|
return Result.succeed(data);
|
}
|
|
@PostMapping(action +"rechargeCallback.action")
|
public ResultMsg rechargeCallback(HttpServletRequest request){
|
String timestamp = request.getParameter("timestamp");
|
String nonce = request.getParameter("nonce");
|
String sign = request.getParameter("sign");
|
String body = request.getParameter("body");
|
|
ResultMsg resultMsg = new ResultMsg();
|
try{
|
log.info("===rechargeCallback===:{}", body);
|
boolean flag = udunClient.checkSign(timestamp, nonce, body, sign);
|
log.info("===rechargeCallback===sign:{}", flag);
|
|
if (!flag){
|
resultMsg.setCode(406);
|
resultMsg.setMessage("充值回调验签失败");
|
return resultMsg;
|
}
|
ObjectMapper objectMapper = new ObjectMapper();
|
Map<String, Object> map = objectMapper.readValue(body, HashMap.class);
|
double amounts = Double.parseDouble(map.get("amount").toString()); // 假设 amount 的值为 1000
|
double decimals = Double.parseDouble(map.get("decimals").toString());
|
double success_amount = amounts / Math.pow(10, decimals);
|
String address = map.get("address").toString();
|
Integer status = Integer.valueOf(map.get("status").toString());
|
/*RechargeBlockchainOrder blockchainOrder = rechargeBlockchainOrderService.getOne(new LambdaQueryWrapper<>(RechargeBlockchainOrder.class)
|
.eq(RechargeBlockchainOrder::getSucceeded, 0)
|
.eq(RechargeBlockchainOrder::getChannelAddress, address).last(" limit 1 "));
|
if(ObjectUtil.isEmpty(blockchainOrder)) {
|
resultMsg.setCode(200);
|
return resultMsg;
|
}*/
|
|
//查询地址订单
|
RechargeBlockchainOrder blockchainOrder = (RechargeBlockchainOrder)redisTemplate.opsForValue().get(address);
|
if (blockchainOrder == null){
|
resultMsg.setCode(200);
|
return resultMsg;
|
}
|
blockchainOrder.setAddress(null);
|
blockchainOrder.setVolume(success_amount);
|
blockchainOrder.setImg(null);
|
blockchainOrder.setSucceeded(0);
|
blockchainOrder.setChannelAddress(address);
|
blockchainOrder.setTx("");
|
rechargeBlockchainOrderService.saveOrder(blockchainOrder);
|
SysUser user = sysUserService.getSysUserById(Long.getLong(blockchainOrder.getPartyId()));
|
|
log.info("===rechargeCallback==d=blockchainOrder:{}", blockchainOrder);
|
if (status == 3) { //交易成功
|
rechargeBlockchainOrderService.manualReceipt(1,blockchainOrder.getOrderNo(), BigDecimal.valueOf(success_amount),user.getUsername());
|
} else if(status == 2) { //驳回
|
rechargeBlockchainOrderService.refusalApply(blockchainOrder.getUuid(), "订单失败:" + status, user.getUsername());
|
}
|
resultMsg.setCode(200);
|
return resultMsg;
|
}catch (Exception e){
|
resultMsg.setCode(500);
|
resultMsg.setMessage("回调处理失败");
|
return resultMsg;
|
}
|
}
|
|
/**
|
* 根据第三方充值链接
|
*/
|
@RequestMapping(action + "getThirdUrl.action")
|
public Result getThirdUrl(HttpServletRequest request) throws IOException {
|
|
String key = this.sysparaService.find("third_key").getSvalue();
|
String merchant_no = this.sysparaService.find("third_id").getSvalue();
|
int i = (int) (Math.random() * 900) + 100;
|
//商户号
|
//10位时间戳
|
String timestamp = "" + System.currentTimeMillis() / 1000;
|
String amount = request.getParameter("amount");
|
//法币名称
|
String fiat_currency = request.getParameter("fiat_currency");
|
//订单号
|
String merchant_ref = System.currentTimeMillis() + "" + i;
|
//产品名称
|
String product = "ERC20Buy";
|
String sign_type = "MD5";
|
Map<String, String> requestparam = new HashMap<>();
|
JSONObject params = new JSONObject(new LinkedHashMap<>());
|
JSONObject extra = new JSONObject(new LinkedHashMap<>());
|
extra.put("fiat_currency", fiat_currency);
|
params.put("merchant_ref", merchant_ref);
|
params.put("product", product);
|
params.put("amount", amount);
|
params.put("extra", extra);
|
String waitsign = merchant_no + params + sign_type + timestamp + key;
|
String sign = MD5.sign(waitsign);
|
requestparam.put("merchant_no", merchant_no);
|
requestparam.put("params", params.toJSONString());
|
requestparam.put("sign", sign);
|
requestparam.put("sign_type", sign_type);
|
requestparam.put("timestamp", params.toJSONString());
|
String result = "";
|
RequestBody body = new FormBody.Builder()
|
.add("merchant_no", merchant_no)
|
.add("timestamp", timestamp)
|
.add("sign_type", sign_type)
|
.add("params", params.toString())
|
.add("sign", sign)
|
.build();
|
Request requestParm = new Request.Builder()
|
.url(threedUrl)
|
.method("POST", body)
|
.addHeader("Content-Type", "application/x-www-form-urlencoded")
|
.build();
|
try {
|
Response response = okHttpClient.newCall(requestParm).execute();
|
result = response.body().string();
|
} catch (Exception e) {
|
throw new YamiShopBindException("请求第三方失败");
|
}
|
JSONObject resultJson = JSON.parseObject(result);
|
Integer code = resultJson.getInteger("code");
|
if (code == 200) {
|
JSONObject resultParams = resultJson.getJSONObject("params");
|
return Result.succeed(resultParams.getString("payurl"));
|
} else {
|
return Result.failed(resultJson.getString("message"));
|
|
}
|
}
|
}
|