1.业务背景
因为公司做的系统跟淘宝有很大一部分的联系,所以涉及电商类的接口比较多,今天在对接礼品公司,对方的接口需要使用加签的方式。像这些接口,双方为了保证数据参数在传输过程中未经过篡改,一般都会需要对接口数据进行加签(不知道为什么像大淘客之类的却没有做这一块,可能是为了使用方便吧),然后在接口服务器端对接口参数进行验签,确保两个签名是一样的,验签通过之后再进行业务逻辑的处理。这里说一下我的处理思路。签名算法网上有很多,这里不做过多的介绍,我这里使用的是MD5算法加密。
2、处理思路
双方约定好,需要进行加签的规则,比如ASCII算法进行排序后加签再转换大小写,如:http://XXX.api.XXX.cn/API/XXX?appKey=yourAppKey&AppSecret=yourAppSecret×tamp=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×tamp=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