1. 程式人生 > 實用技巧 >Java HTTP POST請求,介面引數加簽,驗籤的操作方法

Java HTTP POST請求,介面引數加簽,驗籤的操作方法

1.業務背景

  因為公司做的系統跟淘寶有很大一部分的聯絡,所以涉及電商類的介面比較多,今天在對接禮品公司,對方的介面需要使用加簽的方式。像這些介面,雙方為了保證資料引數在傳輸過程中未經過篡改,一般都會需要對介面資料進行加簽(不知道為什麼像大淘客之類的卻沒有做這一塊,可能是為了使用方便吧),然後在介面伺服器端對介面引數進行驗籤,確保兩個簽名是一樣的,驗籤通過之後再進行業務邏輯的處理。這裡說一下我的處理思路。簽名演算法網上有很多,這裡不做過多的介紹,我這裡使用的是MD5演算法加密。

2、處理思路

  雙方約定好,需要進行加簽的規則,比如ASCII演算法進行排序後加籤再轉換大小寫,如:http://XXX.api.XXX.cn/API/XXX?appKey=yourAppKey&AppSecret=yourAppSecret&timestamp=time&product=XXXX&sign=XXXXX,這裡的引數是timestamp=time&product=XXXX,我這裡只需要把引數拼接起來就可以了,即引數timestamp+product就可以了,然後再呼叫md5加簽一次,再把這個值放到sign裡,發給介面方,介面方接受到之後就會根據sign進行解析

3.例項練習

import java.io.UnsupportedEncodingException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

public class Demo {
    static String appKey = "yourAppKey";
    static String AppSecret = "youreAppSecret";
    static String URL = "http://XXX.api.XXX.cn/API/XXX?appKey=yourAppKey&AppSecret=yourAppSecret&timestamp=time&product=XXXX&sign=XXXXX";
    
public static void main(String[] args) throws Exception { Map<String, Object> MDParams = new HashMap(); String timestamp =DateUtils.getDate("yyyy-MM-dd HH:mm:ss"); MDParams.put("timestamp",timestamp); String sign = createSign(MDParams,AppSecret); Map map
= new HashMap(); map.put("timestamp",timestamp); map.put("sign",sign); String params = mapToString(map); String result = HttpUtil.postGeneralUrl(URL,"application/x-www-form-urlencoded;charset=UTF-8", params, "UTF-8"); System.out.println(result); } private static String createSign(Map<String, Object> params, String accessSecret) throws UnsupportedEncodingException { Set<String> keysSet = params.keySet(); Object[] keys = keysSet.toArray(); Arrays.sort(keys); StringBuilder temp = new StringBuilder(); boolean first = true; for (Object key : keys) { Object value = params.get(key); String valueString = ""; if (null != value) { valueString = String.valueOf(value); } temp.append(valueString); } temp.append(accessSecret); StringBuilder temp2 = new StringBuilder(); temp2.append(accessSecret); temp2.append(temp); return MD5Util.md5Encrypt32Upper(temp2.toString()).toUpperCase(); } private static String mapToString(Map<String, Object> params){ Set<String> keysSet = params.keySet(); Object[] keys = keysSet.toArray(); Arrays.sort(keys); StringBuilder temp = new StringBuilder(); boolean first = true; for (Object key : keys) { if (first) { first = false; } else { temp.append("&"); } temp.append(key).append("="); Object value = params.get(key); String valueString = ""; if (null != value) { valueString = String.valueOf(value); } temp.append(valueString); } return temp.toString(); } }
DateUtils.java

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.FastDateFormat;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.management.ManagementFactory;
import java.text.ParseException;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

/**
 * 日期處理
 */
public class DateUtils extends org.apache.commons.lang3.time.DateUtils {
    private final static Logger logger = LoggerFactory.getLogger(DateUtils.class);

    private static String[] parsePatterns = { "yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM-dd HH",
            "yyyy-MM", "yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyy/MM/dd HH", "yyyy/MM",
            "yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm", "yyyy.MM.dd HH", "yyyy.MM", "yyyy年MM月dd日",
            "yyyy年MM月dd日 HH時mm分ss秒", "yyyy年MM月dd日 HH時mm分", "yyyy年MM月dd日 HH時", "yyyy年MM月", "yyyy" };

    /**
     * 獲取
     * 從今天往前beforeDay天到明天凌晨的時間範圍,集合範圍: [開始時間, 結束時間)
     * @return
     */
    public static Date[] getTodayDateRange(int beforeDay) {
        Date startDate = DateUtils.truncate(new Date(), Calendar.DATE);
        Date endDate = DateUtils.addDays(startDate, 1);
        
        if (beforeDay > 0) {
            startDate = DateUtils.addDays(startDate, -beforeDay);
        }
        
        return new Date[] {startDate, endDate};
    }
    
    /**
     * 獲取
     * 從今天往前beforeDay天到明天凌晨的時間範圍,集合範圍: [開始時間, 結束時間)
     * @return
     */
    public static String[] getTodayDateRangeStr(int beforeDay) {
        Date startDate = DateUtils.truncate(new Date(), Calendar.DATE);
        Date endDate = DateUtils.addDays(startDate, 1);
        
        if (beforeDay > 0) {
            startDate = DateUtils.addDays(startDate, -beforeDay);
        }
        
        String startDateStr = formatDate(startDate, parsePatterns[1]);
        String endDateStr = formatDate(endDate, parsePatterns[1]);
        
        return new String[] {startDateStr, endDateStr};
    }
    
    /**
     * 獲取
     * 從今天往前beforeDay天到明天凌晨的時間範圍,集合範圍: [開始時間, 結束時間)
     * @return
     */
    public static String[] getTodayDateRangeStr0(int beforeDay) {
        
        Date[] dates = getTodayDateRange(beforeDay);
        String startDateStr = formatDate(dates[0], parsePatterns[0]);
        String endDateStr = formatDate(dates[1], parsePatterns[0]);
        
        return new String[] {startDateStr, endDateStr};
    }
    
    /**
     * 得到日期字串 ,轉換格式(yyyy-MM-dd)
     */
    public static String formatDate(Date date) {
        return formatDate(date, "yyyy-MM-dd");
    }

    /**
     * 得到日期字串 預設格式(yyyy-MM-dd) pattern可以為:"yyyy-MM-dd" "HH:mm:ss" "E"
     */
    public static String formatDate(long dateTime, String pattern) {
        return formatDate(new Date(dateTime), pattern);
    }

    /**
     * 得到日期字串 預設格式(yyyy-MM-dd) pattern可以為:"yyyy-MM-dd" "HH:mm:ss" "E"
     */
    public static String formatDate(Date date, String pattern) {
        String formatDate = null;
        if (date != null) {
//                if (StringUtils.isNotBlank(pattern)) {
//                    formatDate = DateFormatUtils.format(date, pattern);
//                } else {
//                    formatDate = DateFormatUtils.format(date, "yyyy-MM-dd");
//                }
            if (StringUtils.isBlank(pattern)) {
                pattern = "yyyy-MM-dd";
            }
            formatDate = FastDateFormat.getInstance(pattern).format(date);
        }
        return formatDate;
    }

    /**
     * 得到日期時間字串,轉換格式(yyyy-MM-dd HH:mm:ss)
     */
    public static String formatDateTime(Date date) {
        return formatDate(date, "yyyy-MM-dd HH:mm:ss");
    }

    /**
     * 得到當前日期字串 格式(yyyy-MM-dd)
     */
    public static String getDate() {
        return getDate("yyyy-MM-dd");
    }

    /**
     * 得到當前日期字串 格式(yyyy-MM-dd) pattern可以為:"yyyy-MM-dd" "HH:mm:ss" "E"
     */
    public static String getDate(String pattern) {
//            return DateFormatUtils.format(new Date(), pattern);
        return FastDateFormat.getInstance(pattern).format(new Date());
    }

    /**
     * 得到當前日期前後多少天,月,年的日期字串
     * 
     * @param pattern 格式(yyyy-MM-dd) pattern可以為:"yyyy-MM-dd" "HH:mm:ss" "E"
     * @param amont   數量,前為負數,後為正數
     * @param type    型別,可參考Calendar的常量(如:Calendar.HOUR、Calendar.MINUTE、Calendar.SECOND)
     * @return
     */
    public static String getDate(String pattern, int amont, int type) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());
        calendar.add(type, amont);
//            return DateFormatUtils.format(calendar.getTime(), pattern);
        return FastDateFormat.getInstance(pattern).format(calendar.getTime());
    }
    
    /**
     * by hzw
     * 得到傳遞時間前後 多少小時,天,月的日期   
     * @param time   外部傳入的日期時間
     * @param amont  數量,前為負數,後為正數
     * @param type   型別,可參考Calendar的常量(如:Calendar.HOUR、Calendar.MINUTE、Calendar.SECOND)
     * @return
     */
    public static Date getDate(Date time ,int amont, int type) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(time);
        calendar.add(type, amont);
        return calendar.getTime(); 
    }

    /**
     * 得到當前時間字串 格式(HH:mm:ss)
     */
    public static String getTime() {
        return formatDate(new Date(), "HH:mm:ss");
    }

    /**
     * 得到當前日期和時間字串 格式(yyyy-MM-dd HH:mm:ss)
     */
    public static String getDateTime() {
        return formatDate(new Date(), "yyyy-MM-dd HH:mm:ss");
    }

    /**
     * 得到當前年份字串 格式(yyyy)
     */
    public static String getYear() {
        return formatDate(new Date(), "yyyy");
    }

    /**
     * 得到當前月份字串 格式(MM)
     */
    public static String getMonth() {
        return formatDate(new Date(), "MM");
    }

    /**
     * 得到當天字串 格式(dd)
     */
    public static String getDay() {
        return formatDate(new Date(), "dd");
    }

    /**
     * 得到當前星期字串 格式(E)星期幾
     */
    public static String getWeek() {
        return formatDate(new Date(), "E");
    }

    /**
     * 日期型字串轉化為日期 格式 see to DateUtils#parsePatterns
     */
    public static Date parseDate(Object str) {
        if (str == null) {
            return null;
        }
        try {
            return parseDate(str.toString(), parsePatterns);
        } catch (ParseException e) {
            return null;
        }
    }

    /**
     * 獲取過去的天數
     * 
     * @param date
     * @return
     */
    public static long pastDays(Date date) {
        long t = System.currentTimeMillis() - date.getTime();
        return t / (24 * 60 * 60 * 1000);
    }

    /**
     * 獲取過去的小時
     * 
     * @param date
     * @return
     */
    public static long pastHour(Date date) {
        long t = System.currentTimeMillis() - date.getTime();
        return t / (60 * 60 * 1000);
    }

    /**
     * 獲取過去的分鐘
     * 
     * @param date
     * @return
     */
    public static long pastMinutes(Date date) {
        long t = System.currentTimeMillis() - date.getTime();
        return t / (60 * 1000);
    }

    /**
     * 獲取兩個日期之間的天數
     * 
     * @param before
     * @param after
     * @return
     */
    public static double getDistanceOfTwoDate(Date before, Date after) {
        long beforeTime = before.getTime();
        long afterTime = after.getTime();
        return (afterTime - beforeTime) / (1000 * 60 * 60 * 24);
    }

    /**
     * 獲取某月有幾天
     * 
     * @param date 日期
     * @return 天數
     */
    public static int getMonthHasDays(Date date) {
//            String yyyyMM = new SimpleDateFormat("yyyyMM").format(date);
        String yyyyMM = FastDateFormat.getInstance("yyyyMM").format(date);
        String year = yyyyMM.substring(0, 4);
        String month = yyyyMM.substring(4, 6);
        String day31 = ",01,03,05,07,08,10,12,";
        String day30 = "04,06,09,11";
        int day = 0;
        if (day31.contains(month)) {
            day = 31;
        } else if (day30.contains(month)) {
            day = 30;
        } else {
            int y = Integer.parseInt(year);
            if ((y % 4 == 0 && (y % 100 != 0)) || y % 400 == 0) {
                day = 29;
            } else {
                day = 28;
            }
        }
        return day;
    }

    /**
     * 獲取日期是當年的第幾周
     * 
     * @param date
     * @return
     */
    public static int getWeekOfYear(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        return cal.get(Calendar.WEEK_OF_YEAR);
    }

    /**
     * 獲取一天的開始時間(如:2015-11-3 00:00:00.000)
     * 
     * @param date 日期
     * @return
     */
    public static Date getOfDayFirst(Date date) {
        if (date == null) {
            return null;
        }
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }

    /**
     * 獲取一天的最後時間(如:2015-11-3 23:59:59.999)
     * 
     * @param date 日期
     * @return
     */
    public static Date getOfDayLast(Date date) {
        if (date == null) {
            return null;
        }
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.HOUR_OF_DAY, 23);
        calendar.set(Calendar.MINUTE, 59);
        calendar.set(Calendar.SECOND, 59);
        calendar.set(Calendar.MILLISECOND, 999);
        return calendar.getTime();
    }

    /**
     * 獲取伺服器啟動時間
     * 
     * @param date
     * @return
     */
    public static Date getServerStartDate() {
        long time = ManagementFactory.getRuntimeMXBean().getStartTime();
        return new Date(time);
    }

    /**
     * 格式化為日期範圍字串
     * 
     * @param beginDate 2018-01-01
     * @param endDate   2018-01-31
     * @return 2018-01-01 ~ 2018-01-31
     * @author ThinkGem
     */
    public static String formatDateBetweenString(Date beginDate, Date endDate) {
        String begin = DateUtils.formatDate(beginDate);
        String end = DateUtils.formatDate(endDate);
        if (StringUtils.isNoneBlank(begin, end)) {
            return begin + " ~ " + end;
        }
        return null;
    }

    /**
     * 解析日期範圍字串為日期物件
     * 
     * @param dateString 2018-01-01 ~ 2018-01-31
     * @return new Date[]{2018-01-01, 2018-01-31}
     * @author ThinkGem
     */
    public static Date[] parseDateBetweenString(String dateString) {
        Date beginDate = null;
        Date endDate = null;
        if (StringUtils.isNotBlank(dateString)) {
            String[] ss = StringUtils.split(dateString, "~");
            if (ss != null && ss.length == 2) {
                String begin = StringUtils.trim(ss[0]);
                String end = StringUtils.trim(ss[1]);
                if (StringUtils.isNoneBlank(begin, end)) {
                    beginDate = DateUtils.parseDate(begin);
                    endDate = DateUtils.parseDate(end);
                }
            }
        }
        return new Date[] { beginDate, endDate };
    }

    public static String getToDay() {
        Date toDay = truncate(new Date(), Calendar.DATE);
        return formatDate(toDay);
    }

    public static String getTomorrow() {
        Date toDay = truncate(new Date(), Calendar.DATE);
        return formatDate( addDays(toDay, 1));
    }

    /**
     * 獲取
     * 從今天往前beforeDay天到明天凌晨的時間範圍,集合範圍: [開始時間, 結束時間)
     * @return
     */
    public static String[] getTodayDateRangeStrByTJY(int beforeDay) {

        Date[] dates = getTodayDateRange(beforeDay);
        String startDateStr = formatDate(dates[0], parsePatterns[1]);
        String endDateStr = formatDate(dates[1], parsePatterns[1]);

        return new String[] {startDateStr, endDateStr};
    }

    public static Date strToDate(String strDate) {

        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");

        ParsePosition pos = new ParsePosition(0);

        Date strtodate = formatter.parse(strDate, pos);

        return strtodate;

    }

}
View Code

HttpUtil.java

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.List;
import java.util.Map;

/**
 * http 工具類
 */
public class HttpUtil {

    public static String post(String requestUrl, String accessToken, String params)
            throws Exception {
        String contentType = "application/x-www-form-urlencoded";
        return HttpUtil.post(requestUrl, accessToken, contentType, params);
    }

    public static String post(String requestUrl, String accessToken, String contentType, String params)
            throws Exception {
        String encoding = "UTF-8";
        if (requestUrl.contains("nlp")) {
            encoding = "GBK";
        }
        return HttpUtil.post(requestUrl, accessToken, contentType, params, encoding);
    }

    public static String post(String requestUrl, String accessToken, String contentType, String params, String encoding)
            throws Exception {
        String url = requestUrl + "?access_token=" + accessToken;
        return HttpUtil.postGeneralUrl(url, contentType, params, encoding);
    }

    public static String postGeneralUrl(String generalUrl, String contentType, String params, String encoding)
            throws Exception {
        URL url = new URL(generalUrl);
        // 開啟和URL之間的連線
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        connection.setRequestMethod("POST");
        // 設定通用的請求屬性
        connection.setRequestProperty("Content-Type", contentType);
        connection.setRequestProperty("Connection", "Keep-Alive");
        connection.setUseCaches(false);
        connection.setDoOutput(true);
        connection.setDoInput(true);

        // 得到請求的輸出流物件
        DataOutputStream out = new DataOutputStream(connection.getOutputStream());
        out.write(params.getBytes(encoding));
        out.flush();
        out.close();

        // 建立實際的連線
        connection.connect();
        // 獲取所有響應頭欄位
        Map<String, List<String>> headers = connection.getHeaderFields();
        // 遍歷所有的響應頭欄位
        for (String key : headers.keySet()) {
            System.err.println(key + "--->" + headers.get(key));
        }
        // 定義 BufferedReader輸入流來讀取URL的響應
        BufferedReader in = null;
        in = new BufferedReader(
                new InputStreamReader(connection.getInputStream(), encoding));
        String result = "";
        String getLine;
        while ((getLine = in.readLine()) != null) {
            result += getLine;
        }
        in.close();
        System.err.println("result:" + result);
        return result;
    }
}
View Code