对接阿里马上放心接口,进行追溯码入库以及获取关联追溯码。平台基本代码很完善,直接复制便可以使用,也可根据功能修改以下代码。
固定参数
公司参数使用*
代替,替换为自己的参数。
private static String URL = "http://gw.api.taobao.com/router/rest";
private static String APPKEY = "****";
private static String SECRET = "****";
private static String UPLOADINOUTBILL_METHOD = "alibaba.alihealth.drugtrace.top.yljg.uploadinoutbill";
private static String RELATION_METHOD = "alibaba.alihealth.drugtrace.top.yljg.query.relation";
private static String FORMAT = "json";
private static String REFENTID = "****";
private static String V = "2.0";
private static String PARTNER_ID = "top-apitools";
private static String SIGN_METHOD = "md5";
获取sign工具类
获取sign时需注意将partner_id
放入map中,否则获取到的sign
会校验失败
public class SignUtil {
public static String signTopRequest(Map<String, String> params, String secret, String signMethod) throws IOException {
// 第一步:检查参数是否已经排序
String[] keys = params.keySet().toArray(new String[0]);
Arrays.sort(keys);
// 第二步:把所有参数名和参数值串在一起
StringBuilder query = new StringBuilder();
if (Constants.SIGN_METHOD_MD5.equals(signMethod)) {
query.append(secret);
}
for (String key : keys) {
String value = params.get(key);
if (StringUtils.areNotEmpty(key, value)) {
query.append(key).append(value);
}
}
// 第三步:使用MD5/HMAC加密
byte[] bytes;
if (Constants.SIGN_METHOD_HMAC.equals(signMethod)) {
bytes = encryptHMAC(query.toString(), secret);
} else {
query.append(secret);
bytes = encryptMD5(query.toString());
}
// 第四步:把二进制转化为大写的十六进制(正确签名应该为32大写字符串,此方法需要时使用)
return byte2hex(bytes);
}
public static byte[] encryptHMAC(String data, String secret) throws IOException {
byte[] bytes = null;
try {
SecretKey secretKey = new SecretKeySpec(secret.getBytes(Constants.CHARSET_UTF8), "HmacMD5");
Mac mac = Mac.getInstance(secretKey.getAlgorithm());
mac.init(secretKey);
bytes = mac.doFinal(data.getBytes(Constants.CHARSET_UTF8));
} catch (GeneralSecurityException gse) {
throw new IOException(gse.toString());
}
return bytes;
}
public static byte[] encryptMD5(String data) throws IOException {
return encryptMD5(data.getBytes(Constants.CHARSET_UTF8));
}
public static byte[] encryptMD5(byte[] data) throws IOException {
byte[] bytes = null;
try {
MessageDigest md = MessageDigest.getInstance("MD5");
bytes = md.digest(data);
} catch (GeneralSecurityException gse) {
throw new IOException(gse.toString());
}
return bytes;
}
public static String byte2hex(byte[] bytes) {
StringBuilder sign = new StringBuilder();
for (int i = 0; i < bytes.length; i++) {
String hex = Integer.toHexString(bytes[i] & 0xFF);
if (hex.length() == 1) {
sign.append("0");
}
sign.append(hex.toUpperCase());
}
return sign.toString();
}
}
定时任务自动入库
因业务需要,当追溯码进行入库后,需获取关联追溯码存入数据库,因入库后马上获取关联追溯码导致无法获取到数据,故使用Thread.sleep(2000);
睡眠2秒后获取关联追溯码。
/**
* 追溯码入库
*
* @throws SQLException
*/
@Scheduled(cron = "*/5 * * * * ?")//5秒一次
@Async("OmsScheduler")
@Transactional(rollbackFor = Exception.class)
public void stockCheck() {
log.debug("追溯码入库----开始" + getDataTime());
try {
String sql = "select refEntId,traceCode,id from order_traceability_code where isStore='0'";
List<Map<String, Object>> list = source.getData(sql);
List<String> updateList = new ArrayList<>();
String updateSql = "update order_traceability_code set CYPZSM='{CYPZSM}',isAli='{isAli}',isStore='{isStore}' where id='{id}'";
for (Map<String, Object> traceMap : list) {
String fromUserId = traceMap.get("refEntId").toString();
String traceCode = traceMap.get("traceCode").toString();
String id = traceMap.get("id").toString();
Date date = new Date();
String str = "yyy-MM-dd HH:mm:ss";
SimpleDateFormat sdf = new SimpleDateFormat(str);
String timestamp = sdf.format(date);
Map map = new HashMap();
map.put("app_key", APPKEY);
map.put("method", UPLOADINOUTBILL_METHOD);
map.put("v", V);
map.put("timestamp", timestamp);
map.put("partner_id", PARTNER_ID);
map.put("sign_method", SIGN_METHOD);
map.put("format", FORMAT);
map.put("ref_user_id", REFENTID);
map.put("bill_code", UuidUtil.get32UUID());
map.put("bill_time", timestamp);
map.put("to_user_id", REFENTID);
map.put("bill_type", "102");
map.put("client_type", "2");
map.put("trace_codes", traceCode);
map.put("physic_type", "3");
map.put("from_user_id", fromUserId);
try {
String sign = SignUtil.signTopRequest(map, SECRET, SIGN_METHOD);
map.put("sign", sign);
String resultString = doGet(URL, map);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
Thread.sleep(2000);//睡眠2s
for (Map<String, Object> traceMap : list) {
String traceCode = traceMap.get("traceCode").toString();
String id = traceMap.get("id").toString();
//查询关联追溯码
String cypzsm = getCYPZSM(traceCode);
String isAli = "1";
if (StringUtils.isEmpty(cypzsm)) {
isAli = "0";
cypzsm = traceCode;
}
updateList.add(updateSql.replace("{CYPZSM}", cypzsm)
.replace("{isAli}", isAli)
.replace("{isStore}", "1")
.replace("{id}", id));
}
//执行更新SQL
source.batchExecute(updateList);
} catch (Exception e) {
e.printStackTrace();
log.error(e.getMessage());
}
log.debug("追溯码入库----结束" + getDataTime());
}
关联追溯码
获取关联追溯码需先使用接口进行入库操作,否则返回“非本企业经营的追溯码”。
/**
* 查询关联追溯码
*
* @param code
* @return
*/
private String getCYPZSM(String code) throws Exception {
String CYPZSM = "";
Date date = new Date();
String str = "yyy-MM-dd HH:mm:ss";
SimpleDateFormat sdf = new SimpleDateFormat(str);
String timestamp = sdf.format(date);
Map map = new HashMap();
map.put("app_key", APPKEY);
map.put("method", RELATION_METHOD);
map.put("v", V);
map.put("timestamp", timestamp);
map.put("partner_id", PARTNER_ID);
map.put("sign_method", SIGN_METHOD);
map.put("format", FORMAT);
map.put("des_ref_ent_id", REFENTID);
map.put("ref_ent_id", REFENTID);
map.put("code", code);
String sign = SignUtil.signTopRequest(map, SECRET, SIGN_METHOD);
map.put("sign", sign);
String resultString = doGet(URL, map);
// 将JSON字符串转换为HashMap
HashMap<String, Object> rspMap = JSON.parseObject(resultString, HashMap.class);
JSONObject result = (JSONObject) ((JSONObject) rspMap.get("alibaba_alihealth_drugtrace_top_yljg_query_relation_response")).get("result");
String response_success = String.valueOf(result.get("response_success"));
if ("true".equals(response_success)) {
JSONArray codeInfoArray = result.getJSONObject("model_list")
.getJSONArray("code_relation_dto")
.getJSONObject(0)
.getJSONObject("code_relation_list")
.getJSONArray("code_info");
StringBuilder codesWithLevelOne = new StringBuilder();
for (int i = 0; i < codeInfoArray.size(); i++) {
JSONObject codeInfo = codeInfoArray.getJSONObject(i);
if ("1".equals(codeInfo.getString("code_pack_level"))) {
if (codesWithLevelOne.length() > 0) {
codesWithLevelOne.append(",");
}
codesWithLevelOne.append(codeInfo.getString("code"));
}
}
CYPZSM = codesWithLevelOne.toString();
}
//解析json
return CYPZSM;
}
请求接口
/**
* 请求接口
*
* @param url
* @param param
* @return
*/
public String doGet(String url, Map<String, String> param) {
// 创建Httpclient对象
CloseableHttpClient httpclient = HttpClients.createDefault();
String resultString = "";
CloseableHttpResponse response = null;
try {
// 创建uri
URIBuilder builder = new URIBuilder(url);
if (param != null) {
for (String key : param.keySet()) {
builder.addParameter(key, param.get(key));
}
}
URI uri = builder.build();
// 创建http GET请求
HttpGet httpGet = new HttpGet(uri);
// 执行请求
response = httpclient.execute(httpGet);
// 判断返回状态是否为200
if (response.getStatusLine().getStatusCode() == 200) {
resultString = EntityUtils.toString(response.getEntity(), "UTF-8");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (response != null) {
response.close();
}
httpclient.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return resultString;
}