Authored by mali

上链迁移

... ... @@ -21,4 +21,6 @@ public interface ProductChainMapper {
List<ProductChain> selectProductChain();
int updateTransactionId(@Param("tagId")String tagId, @Param("transactionId")String transaction_id);
int updateProductChain(ProductChain chain);
}
\ No newline at end of file
... ...
... ... @@ -19,4 +19,6 @@ public interface ProductInfoMapper {
int updateByPrimaryKey(ProductInfo record);
List<ProductInfo> selectIsuploadIsZero();
int insertProductInfo(ProductInfo productInfo);
}
\ No newline at end of file
... ...
package com.yoho.product.model;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
@Data
@ToString
@Builder
@NoArgsConstructor
public class ProductChain {
private String tagId;
... ... @@ -8,36 +17,4 @@ public class ProductChain {
private String transactionId;
private Integer transactionTime;
public String getTagId() {
return tagId;
}
public void setTagId(String tagId) {
this.tagId = tagId == null ? null : tagId.trim();
}
public Long getChainId() {
return chainId;
}
public void setChainId(Long chainId) {
this.chainId = chainId;
}
public String getTransactionId() {
return transactionId;
}
public void setTransactionId(String transactionId) {
this.transactionId = transactionId == null ? null : transactionId.trim();
}
public Integer getTransactionTime() {
return transactionTime;
}
public void setTransactionTime(Integer transactionTime) {
this.transactionTime = transactionTime;
}
}
\ No newline at end of file
... ...
package com.yoho.product.model;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
@Data
@ToString
@Builder
@NoArgsConstructor
public class ProductInfo {
private Long id;
... ... @@ -30,124 +39,4 @@ public class ProductInfo {
private Integer fromPlatform;
private String nfcid;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getProductUrl() {
return productUrl;
}
public void setProductUrl(String productUrl) {
this.productUrl = productUrl == null ? null : productUrl.trim();
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color == null ? null : color.trim();
}
public String getSize() {
return size;
}
public void setSize(String size) {
this.size = size == null ? null : size.trim();
}
public String getGoodsNo() {
return goodsNo;
}
public void setGoodsNo(String goodsNo) {
this.goodsNo = goodsNo == null ? null : goodsNo.trim();
}
public String getSource() {
return source;
}
public void setSource(String source) {
this.source = source == null ? null : source.trim();
}
public String getOwner() {
return owner;
}
public void setOwner(String owner) {
this.owner = owner == null ? null : owner.trim();
}
public String getTransactionTime() {
return transactionTime;
}
public void setTransactionTime(String transactionTime) {
this.transactionTime = transactionTime == null ? null : transactionTime.trim();
}
public String getTagid() {
return tagid;
}
public void setTagid(String tagid) {
this.tagid = tagid == null ? null : tagid.trim();
}
public String getSign() {
return sign;
}
public void setSign(String sign) {
this.sign = sign == null ? null : sign.trim();
}
public Integer getIsupload() {
return isupload;
}
public void setIsupload(Integer isupload) {
this.isupload = isupload;
}
public String getAuthTime() {
return authTime;
}
public void setAuthTime(String authTime) {
this.authTime = authTime == null ? null : authTime.trim();
}
public String getLastTransactionId() {
return lastTransactionId;
}
public void setLastTransactionId(String lastTransactionId) {
this.lastTransactionId = lastTransactionId == null ? null : lastTransactionId.trim();
}
public Integer getFromPlatform() {
return fromPlatform;
}
public void setFromPlatform(Integer fromPlatform) {
this.fromPlatform = fromPlatform;
}
public String getNfcid() {
return nfcid;
}
public void setNfcid(String nfcid) {
this.nfcid = nfcid == null ? null : nfcid.trim();
}
}
\ No newline at end of file
... ...
... ... @@ -20,11 +20,10 @@
delete from product_chain
where tag_id = #{tagId,jdbcType=VARCHAR}
</delete>
<insert id="insert" parameterType="com.yoho.product.model.ProductChain" >
insert into product_chain (tag_id, chain_id, transaction_id,
transaction_time)
values (#{tagId,jdbcType=VARCHAR}, #{chainId,jdbcType=BIGINT}, #{transactionId,jdbcType=VARCHAR},
#{transactionTime,jdbcType=INTEGER})
<insert id="updateProductChain" parameterType="com.yoho.product.model.ProductChain" >
insert into product_chain (tag_id, chain_id, transaction_id, transaction_time)
values (#{tagId,jdbcType=VARCHAR}, #{chainId,jdbcType=BIGINT}, #{transactionId,jdbcType=VARCHAR}, #{transactionTime,jdbcType=INTEGER})
ON DUPLICATE KEY UPDATE transaction_id=#{transactionId, jdbcType=VARCHAR}
</insert>
<insert id="insertSelective" parameterType="com.yoho.product.model.ProductChain" >
insert into product_chain
... ... @@ -82,6 +81,6 @@
select
<include refid="Base_Column_List" />
from product_chain
where transaction_id IS NULL ORDER BY id desc limit 200
where transaction_id IS NULL limit 200
</select>
</mapper>
\ No newline at end of file
... ...
... ... @@ -33,13 +33,13 @@
select
<include refid="Base_Column_List" />
from product_info
where isupload = 0
where isupload = 0 limit 200
</select>
<delete id="deleteByPrimaryKey" parameterType="java.lang.Long" >
delete from product_info
where id = #{id,jdbcType=BIGINT}
</delete>
<insert id="insert" parameterType="com.yoho.product.model.ProductInfo" >
<insert id="insertProductInfo" parameterType="com.yoho.product.model.ProductInfo" >
insert into product_info (id, product_url, color,
size, goods_no, source,
owner, transaction_time, tagid,
... ...
... ... @@ -5,6 +5,7 @@ import com.yoho.ufo.exception.PlatformException;
import com.yoho.ufo.service.INFCService;
import com.yoho.ufo.service.impl.ProductChainService;
import com.yoho.ufo.service.model.ApiResponse;
import com.yohobuy.ufo.model.request.nfc.ProductInfoReq;
import com.yohobuy.ufo.model.request.nfc.UfoNFCRequestBo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
... ... @@ -40,13 +41,13 @@ public class ProductChainController {
* @return
*/
@RequestMapping(value = "/addItem")
public ApiResponse addItem(ProductInfo bo) {
logger.info("nfc.writeIdentify param = {}", bo);
public ApiResponse addItem(ProductInfoReq bo) {
logger.info("nfc.addItem param = {}", bo);
try {
chainService.addItem(bo);
} catch (PlatformException e) {
return new ApiResponse.ApiResponseBuilder().code(e.getCode()).message(e.getMessage()).build();
} catch (Exception e) {
return new ApiResponse.ApiResponseBuilder().code(400).message(e.getMessage()).build();
}
return new ApiResponse.ApiResponseBuilder().message("success").build();
}
... ...
... ... @@ -8,19 +8,51 @@ import com.yoho.product.dal.ProductChainMapper;
import com.yoho.product.dal.ProductInfoMapper;
import com.yoho.product.model.ProductChain;
import com.yoho.product.model.ProductInfo;
import com.yoho.ufo.util.DateUtil;
import com.yohobuy.ufo.model.request.nfc.ProductInfoReq;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.codec.binary.*;
import org.apache.commons.lang3.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import sun.misc.BASE64Encoder;
import javax.annotation.Resource;
import javax.crypto.Cipher;
import javax.crypto.NoSuchPaddingException;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileReader;
import java.lang.reflect.InvocationTargetException;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.*;
import java.util.Base64;
/**
* Created by li.ma on 2020/3/31.
*/
@Service
public class ProductChainService {
private static final Logger logger = LoggerFactory.getLogger(ProductChainService.class);
private static final byte[] priKeyText;
static {
priKeyText = getFileContent("rsa_private_key.pem");
}
@Autowired
private ProductInfoMapper productInfoMapper;
... ... @@ -30,44 +62,61 @@ public class ProductChainService {
@Autowired
private ServiceCaller serviceCaller;
@Resource(name="restTemplate")
private RestTemplate restTemplate;
@Value("${urltrainblock.url}")
private String urltrainblockUrl;
// curl http://40.73.0.117:8078/yoho/post/query POST -H "Content-Type:application/json" -d '"id":"156663177401529"' -v
public void postQuery(String chainId) {
public void postQuery(Long chainId) {
// (String serviceName, String url, Object request, Class<T> responseType, T fallback, int timeout)
Map<String, Object> request = new HashMap<>(); request.put("id", chainId);
AsyncFuture<String> post = serviceCaller.post("ufo-platform.chain", urltrainblockUrl + "/post/query", request, String.class, null, 1);
String response = post.get(1);
JSONObject jsonObject = JSONObject.parseObject(response);
String errorCode = jsonObject.getString("errorCode");
String errorMsg = jsonObject.getString("errorMsg");
HttpHeaders headers = getHttpHeaders("");
HttpEntity<String> formEntity = getStringHttpEntity(request, headers);
ResponseEntity<String> response = restTemplate.postForEntity(urltrainblockUrl + "/post/query", formEntity, String.class);
JSONObject jsonObject = JSONObject.parseObject(response.getBody());
String errorCode = jsonObject.getString("errorCode");
JSONObject result = jsonObject.getJSONObject("result");
JSONArray yohoInfos = result.getJSONArray("yohoInfos");
logger.info("postQuery success. chainId is {}, errorCode is {}, result is {}", chainId, errorCode, result);
if (org.apache.commons.lang3.StringUtils.isEmpty(errorCode) && null != result) {
JSONArray yohoInfos = result.getJSONArray("yohoInfos");
int size = yohoInfos.size();
JSONObject item = (JSONObject)yohoInfos.get(0);
String transactionId = item.getString("transactionId");
updateProductChain(ProductChain.builder().chainId(chainId).transactionId(transactionId).build());
}
}
public void postChainInfo(ProductInfo productInfo) {
public void postChainInfo(ProductInfoReq bo, Long id, String sign) {
// (String serviceName, String url, Object request, Class<T> responseType, T fallback, int timeout)
Map<String, Object> request = null;
try {
request = BeanUtils.describe(productInfo);
request = BeanUtils.describe(bo);
} catch (Exception e) {
e.printStackTrace();
}
AsyncFuture<String> post = serviceCaller.post("ufo-platform.chainInfo", urltrainblockUrl + "/post/info", request, String.class, null, 1);
String response = post.get(1);
JSONObject jsonObject = JSONObject.parseObject(response);
String errorCode = jsonObject.getString("errorCode");
HttpHeaders headers = getHttpHeaders(sign);
HttpEntity<String> formEntity = getStringHttpEntity(request, headers);
ResponseEntity<String> response = restTemplate.postForEntity(urltrainblockUrl + "/post/query", formEntity, String.class);
JSONObject jsonObject = JSONObject.parseObject(response.getBody());
String errorMsg = jsonObject.getString("errorMsg");
String result = jsonObject.getString("result");
JSONObject result = jsonObject.getJSONObject("result");
JSONArray yohoInfos = result.getJSONArray("yohoInfos");
logger.info("postChainInfo success. bo is {}, id is {}, errorMsg is {}, result is {}", bo, id, errorMsg, result);
if ("Y".equals(result) || "ID字段重复".equals(errorMsg)) {
updateIsupload(id, 1); // 如果更新成功,则更新数据库字段
}
}
// SELECT * FROM ${TABLE_PRODUCT_CHAIN} WHERE transaction_id IS NULL
... ... @@ -75,29 +124,255 @@ public class ProductChainService {
return productChainMapper.selectProductChain();
}
public int updateProductChain(ProductChain chain) {
return productChainMapper.updateProductChain(chain);
}
// select * from ${TABLE_PRODUCT_INFO} where isupload = :isupload
public List<ProductInfo> queryIsuploadIsZero() {
return productInfoMapper.selectIsuploadIsZero();
}
public int updateIsupload(ProductInfo productInfo) {
return productInfoMapper.updateIsupload(productInfo);
public int updateIsupload(Long id, int isupload) {
ProductInfo build = ProductInfo.builder().isupload(isupload).id(id).build();
return productInfoMapper.updateIsupload(build);
}
public int insertProductInfo(ProductInfo productInfo) {
/*let id = +data.id
let product_url = data.product_url
let color = data.color
let size = data.size
let goods_no = data.goods_no
let source = data.source
let owner = data.owner
let transaction_time = data.transaction_time
let tagid = data.tagid
let sign = data.sign
let isupload = data.isupload || 0
let auth_time = data.auth_time
let last_transaction_id = data.last_transaction_id || ''
let from_platform = data.from_platform || 0 //0为默认UFO, 1为有货
let nfcid = data.nfcid || ''*/
return productInfoMapper.insertProductInfo(productInfo);
}
public int updateIsupload(String tagId, String transaction_id) {
public int updateTransactionId(String tagId, String transaction_id) {
return productChainMapper.updateTransactionId(tagId, transaction_id);
}
// 同步上链的数据
public void addItem(ProductInfo bo) {
public void addItem(ProductInfoReq bo) {
Long generateid = generateid();
logger.info("generateid is : " , generateid);
updatechainSql(bo.getTagid(), generateid, null, Integer.valueOf(bo.getTransaction_time()));
try {
String sign = generateSign(BeanUtils.describe(bo));
logger.info("sign is : " , sign);
insertProductInfo(convertVo(bo, generateid, sign));
postChainInfo(bo, generateid, sign);
} catch (Exception e) {
e.printStackTrace();
}
}
private ProductInfo convertVo(ProductInfoReq bo, Long generateid, String sign) {
return ProductInfo.builder().id(generateid).productUrl(bo.getProduct_url()).color(bo.getColor())
.size(bo.getSize()).goodsNo(bo.getGoods_no()).source(bo.getSource()).owner(bo.getOwner())
.transactionTime(bo.getTransaction_time()).tagid(bo.getTagid()).sign(sign).isupload(0)
.authTime(bo.getAuth_time()).lastTransactionId(null == bo.getLast_transaction_id() ? "" : bo.getLast_transaction_id())
.fromPlatform(null == bo.getFrom_platform() ? 0 : bo.getFrom_platform())
.nfcid(null == bo.getNfcid() ? "" : bo.getNfcid()).build();
}
private void updatechainSql(String tagId, Long chainId, String transactionId, Integer transactionTime) {
ProductChain chain = new ProductChain();
chain.setChainId(chainId);
chain.setTagId(tagId);
chain.setTransactionId(transactionId);
chain.setTransactionTime(transactionTime);
updateProductChain(chain);
}
private String generateid() {
return Math.floor(new Date().getTime()/1000) + "01" + new Random(3).nextInt();
private static Long generateid() {
return Long.valueOf(DateUtil.getCurrentTimeSeconds() + "01" + getRandom(3));
}
// const generateid = () => {
//return Math.floor(new Date().getTime()/1000) + '01' + getRandom(3)
//return Math.floor(new Date().getTime()/1000) + '01' + getRandom(3) 155289842201546
private static int getRandom(int num) {
return (int)Math.floor((Math.random()+Math.floor(Math.random()*9+1))*Math.pow(10,num-1));
}
private static String generateSign(Map<String, Object> params) {
List<String> strings = new ArrayList<>(params.keySet());
Collections.sort(strings);
String str = "";
for(String item : strings) {
str += item + "=" + params.get(item) + "&";
}
String substring = str.substring(0, str.length() - 1);
String hashvalue = md5Hex(str);
// const encodeData = crypto.privateEncrypt(privatekey, Buffer.from(hashvalue)).toString('base64');
String base64Sign = null; //RSA解密
try {
/*Signature sign = Signature.getInstance("SHA1withRSA");
sign.initSign(getPrivateKey());
byte[] bysData = hashvalue.getBytes("UTF-8");
sign.update(bysData);
byte[] signByte = sign.sign();
BASE64Encoder encoder = new BASE64Encoder();
base64Sign = encoder.encode(signByte);*/
base64Sign = sign(hashvalue);
} catch (Exception e) {
e.printStackTrace();
}
return base64Sign;
}
public static String sign(String plainText) {
try {
PKCS8EncodedKeySpec priPKCS8 = new PKCS8EncodedKeySpec(Base64.getDecoder().decode(priKeyText));
KeyFactory keyf = KeyFactory.getInstance("RSA");
PrivateKey prikey = keyf.generatePrivate(priPKCS8);
// 用私钥对信息生成数字签名
Signature signet = Signature.getInstance("MD5withRSA");
signet.initSign(prikey);
signet.update(plainText.getBytes());
byte[] signed = Base64.getEncoder().encode(signet.sign());
return new String(signed);
} catch (java.lang.Exception e) {
System.out.println("签名失败");
e.printStackTrace();
}
return null;
}
/**
* 将字符串进行MD5加密并十六进制编码
*
* @param src 字符串
* @return D5加密并十六进制编码字符串
*/
public static String md5Hex(String src) {
try {
MessageDigest md5 = MessageDigest.getInstance("MD5");
md5.update(src.getBytes(StandardCharsets.UTF_8));
byte[] md = md5.digest();
return new String(md, StandardCharsets.UTF_8);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static byte[] getFileContent(String fileName) {
byte[] data = (byte[])null;
FileInputStream fis = null;
try {
File f = new File(fileName);
data = new byte[(int)f.length()];
fis = new FileInputStream(f);
fis.read(data);
fis.close();
} catch (Exception e) {
return null;
}
return data;
}
/*public static PrivateKey getPrivateKey() {
PrivateKey priKey = null;
try {
FileInputStream fis = new FileInputStream("rsa_private_key.pem");
KeyStore keyStore = KeyStore.getInstance("PKCS12");
char[] pscs = pfxPassword.toCharArray();
keyStore.load(fis, pscs);
priKey = (PrivateKey) (keyStore.getKey(aliasName, pscs));
} catch (Exception e) {
return null;
}
return priKey;
}*/
/**
* 字符串Base64解码
*
* @param src 字符串
* @return 经过Base64解码的字符串
*/
public static String base64Decode(String src) {
if (src == null || src.equals("")) {
return null;
}
// decodeBase64
org.apache.commons.codec.binary.Base64 decoder = new org.apache.commons.codec.binary.Base64();
byte[] deByte = decoder.decode(src.getBytes(StandardCharsets.UTF_8));
return new String(deByte, StandardCharsets.UTF_8).trim();
}
public static void main(String[] args) {
System.out.println();
}
public void postChainInfoEx(ProductInfo item) {
ProductInfoReq build = ProductInfoReq.builder()
.auth_time(item.getAuthTime())
.color(item.getColor())
.from_platform(item.getFromPlatform())
.goods_no(item.getGoodsNo())
.last_transaction_id(item.getLastTransactionId())
.nfcid(item.getNfcid())
.owner(item.getOwner())
.product_url(item.getProductUrl())
.size(item.getSize())
.transaction_time(item.getTransactionTime())
.tagid(item.getTagid())
.source(item.getSource())
.build();
postChainInfo(build, item.getId(), item.getSign());
}
private HttpEntity<String> getStringHttpEntity(Map<String, Object> params, HttpHeaders headers) {
JSONObject jsonObj = new JSONObject();
for(Map.Entry<String, Object> item : params.entrySet()) {
jsonObj.put(item.getKey(), item.getValue());
}
return new HttpEntity<>(jsonObj.toString(), headers);
}
private HttpHeaders getHttpHeaders(String signature) {
HttpHeaders headers = new HttpHeaders();
MediaType type = MediaType.parseMediaType("application/json; charset=UTF-8");
headers.setContentType(type);
headers.add("signature", signature);
return headers;
}
}
... ...
package com.yoho.ufo.service.scheduled;
import com.yoho.product.model.ProductChain;
import com.yoho.product.model.ProductInfo;
import com.yoho.quartz.annotation.JobType;
import com.yoho.quartz.annotation.MisfiredPolicy;
import com.yoho.quartz.annotation.YhJobDef;
... ... @@ -12,6 +14,8 @@ import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* 上链失败的进行上链操作
* @author caoyan
... ... @@ -29,7 +33,11 @@ public class ScheduledProductChain implements YhJob {
public JobProcessResult process(String jobContext) {
LOGGER.info("scheduledProductChain begin.");
List<ProductInfo> productInfos = productChainService.queryIsuploadIsZero();
productInfos.stream().forEach(item -> {
productChainService.postChainInfoEx(item);
});
JobProcessResult result = new JobProcessResult();
... ...
package com.yoho.ufo.service.scheduled;
import com.yoho.product.model.ProductChain;
import com.yoho.quartz.annotation.JobType;
import com.yoho.quartz.annotation.MisfiredPolicy;
import com.yoho.quartz.annotation.YhJobDef;
... ... @@ -12,6 +13,8 @@ import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* 上链失败的进行上链操作
* @author caoyan
... ... @@ -29,8 +32,9 @@ public class ScheduledTransactionChain implements YhJob {
public JobProcessResult process(String jobContext) {
LOGGER.info("scheduledTransactionChain begin.");
List<ProductChain> productChains = productChainService.queryProductChain();
productChains.stream().forEach(item -> productChainService.postQuery(item.getChainId()));
JobProcessResult result = new JobProcessResult();
result.setJobResultCode(JobResultCode.SUCCESS);
... ...
-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQCxYEoJaTCrL121mhKLUzB1oOOJ34nHWXt+QtDIqF8x8fLOjJ0k
w79/eS7Cq29WLS1LwuS9OAkfiXvOhvsrJhsn/erAvSvGH3k5UcVtcEl+mMrb3Zcx
wolHT22YWWxxBxQ78OxWbxVh2zNQ28pWGsDdvmTAueWdJALtzewg8iMDKQIDAQAB
AoGAf2aJxvim3E3JIQbpCulVhSdqRz0n2OeMq8OR8o380gLWQ0T8Gcv/X6/Kxkgc
T+li/2eco8v7wYseQdjxzqwwE/dNOhFVCqJ5ft+QBeSHtDh1hJIQjxrVNqfujauv
wrdtGu/9FMpgVaggraE/6115R0tdgo283dUdHstuf3NPdYECQQDXAd+xKYIJjoFH
UjPptowIaYv4Wo9z/Vc4yVjIa+clylDmSDI9M2Ibc4LOEYkc7h9YE/BsMjfFHPKs
x0DVXNm3AkEA0zG0J5j/vMpXfcB3BV5t84Zlm65FI10HQAhfcgnborm4ag3Am8DC
RRwY4GZqVHctaAelFSTNK2mdR7TqBbiKHwJAc+1GtzcyLgTwH4xrATC0ADUoixgJ
EPkf9jZZ8HZ9gxq60+9JZ0Y1N6fod0NtMnQR4mOd1jidaWJaVl54zpHpsQJBAMG8
3t9UY4X0uL4LSSQLtCGqMJvYCmSeeoArLiOXF3z3kkz3wLEg6xYq6EcyrGg/y8+a
872pvO0OPdICDIyi9VECQQCm/BaNz9Jv/d8N7Pq9o6miMenV2aN3l/61VZ2zRRtI
2ge1AwY+PXUUgB/Um5N9LM+vJxHXwAaUJOjI5HaqnfTM
-----END RSA PRIVATE KEY-----
... ...