Bootstrap

阿里马上放心平台接口对接

对接阿里马上放心接口,进行追溯码入库以及获取关联追溯码。平台基本代码很完善,直接复制便可以使用,也可根据功能修改以下代码。

固定参数

公司参数使用*代替,替换为自己的参数。

    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;
    }


;