1. 签名说明及实例
1.1 假设用户SecretKey为wUDSCOdFibEL6pIQGYgF,请求入参如下:
{
"goods_id": 12345,
"memo": "",
"visit_date": "2018-01-01"
}
1.2 首先,我们要按照key值首字母排序,并去掉value为空的,得到以下参数:
{
"agencyProductId": 12345,
"apiKey": "Ape2hqlBF0sFUUcjbj",
"planDateStr": "test",
"timestamp": "2017-04-13 16:39:10"
}
1.3 将参数名、参数值依次拼接在一起:
agencyProductId=12345&apiKey=Ape2hqlBF0sFUUcjbj&planDateStr=test×tamp=2017-04-13 16:39:10
1.4 在开头和结尾分别加上SecretKey:
wUDSCOdFibEL6pIQGYgF&agencyProductId=12345&apiKey=Ape2hqlBF0sFUUcjbj&planDateStr=test×tamp=2017-04-13 16:39:10&wUDSCOdFibEL6pIQGYgF
1.5 进行MD5加密,并将结果全部转为大写,获得签名值:
B1E24AB111C4D2BDB3FA19545C7338B7
1.6 签名生成结束,请求入参变为:
{
"apiKey": "Ape2hqlBF0sFUUcjbj",
"data": {
"agencyProductId": 12345,
"info": "",
"planDateStr": "test"
},
"sign": "B1E24AB111C4D2BDB3FA19545C7338B7",
"timestamp": "2017-04-13 16:39:10"
}
2. 加密说明及实例
2.1 业务参数在传输之前是明文的JSON对象,例如:
"data": {
"retailOrderId": "15538430T8393205",
"cheCi": "K1237",
"fromStationCode": "BZH",
"passengers": [{
"passengerId": 33292562,
"ticketNo": null,
"passengerName": "张秀勤",
"passportNo": "341222197608254405",
"passportTypeId": "1",
"passportTypeName": "二代身份证",
"piaoType": "1",
…
}]
}
2.2 加密是对data的值进行加密的,加密之后整个消息结构如下:
{
"apiKey": "Ape2hqlBF0sFUUcjbj",
"timestamp": "2015-07-30 12:34:56",
"sign": "C81E00F2CCC228DD8C1D3EB6C69B4260",
"data": "base64ResultTest"
}
3. java版生成签名工具类(准确的定义请参照java版SDK)
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.StringUtils;
import java.security.MessageDigest;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* API签名工具类
*/
public class Signature {
private static final String API_SIGNATURE_KEY ="sign" ;
/**
* 根据入参和密钥获取签名
*
* @author gulingfeng
* @taskId
* @param data
* @param secretKey
* @return
* @throws Exception
*/
// 第一步:获取所有值非空的参数,忽略签名
public static String getSignature(JSONObject data, String secretKey) throws Exception {
List<String> keyList = new ArrayList<String>();
for (Object key : data.keySet()) {
// key为null或者key是签名
if (key == null || API_SIGNATURE_KEY.equalsIgnoreCase(key.toString())) {
continue;
}
// value为null或者为空
if (data.get(key) == null || StringUtils.isBlank(data.get(key).toString())) {
continue;
}
keyList.add(key.toString());
}
// 第二步:按名称排序并拼接成字符串
String[] arrayToSort = keyList.toArray(new String[keyList.size()]);
Arrays.sort(arrayToSort, String.CASE_INSENSITIVE_ORDER);
StringBuilder sb = new StringBuilder(secretKey);
for (String key : arrayToSort) {
sb.append(key);
sb.append(data.get(key));
}
sb.append(secretKey);
//log.info("获取签名方法,生成签名第二步结果为" + sb.toString());
// 第三步:MD5加密并转换成大写的16进制
MessageDigest md = MessageDigest.getInstance("MD5");
return byte2hex(md.digest(sb.toString().getBytes()));
}
private 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();
}
public static void main(String[] args) throws Exception {
JSONObject map = new JSONObject();
map.put("apiKey", "Vq8u4bqAdM2TUh4YZX");
map.put("timestamp", "2015-09-16 13:01:25");
map.put("agencyProductId", "11402");
map.put("planDateStr", "2015-11-01");
String signature = getSignature(map, "S5QquHJceY1es5ItyQxV");
map.put(API_SIGNATURE_KEY,signature);
System.out.println(map.toString());
}
}