1. 出现场景: 支付系统需要生成签名加密,有一次我接了一个接口,需要前端的同事传递一个sign参数(表单值按顺序拼接,并拼上私钥值进行md5运算)
问题: js 不像java 有map.list 等集合框架,也没有很现成的排序方法,
js 也不像java 提供jca 等加密框架,对各种加密算法进行支持
解决: 1. 于是就干脆手写了一个javascript 的排序方法,
2.在网上找到一个牛人写的javascript 的 md5.js (此页面还包含其他加密算法的javascript实现)
自定义手写的javascript 的排序js , sortArrString.js
主方法为getKeySort(传入的数组)对象,返回拍过序的数组对象,
内部排序算法是通过: 冒泡排序
规则 :是按字母顺序升序进行排序,按参数名的第一个字母进行比较,如果相同则比较第二个,直到排出大小
js 的 == 可以比较字符串的大小
/**
* 测试demo ,假设传入的情况
* 是数组,返回数组按字母顺序升序
* @author kzcming
*
* var signStr = {
account:"97987985",
username:"0004",
pay_star_type:"pay_star_ggm",
service_type:"gm_ibc",
game_code :"1",
}
getKeySort(getObjectKey(signStr));*/
/**
* 传入对象 ,返回对象的属性数组
*/
function getObjectKey(obj){
return Object.keys(obj);
}
/**
* 传入数组
* 按字母顺序,升序
* 冒泡排序
*/
function getKeySort(strArr){
var count = 0;
var compareInt = 0;
for (var i = 0; i < strArr.length; i++) {
for (var j = 0; j < strArr.length - 1 - i; j++) {
/*if(strArr [j].substring(0,1) > strArr[j + 1].substring(0,1)){
var temp = strArr[j + 1];
strArr[j + 1] = strArr[j];
strArr[j] = temp;
}
if(strArr [j].substring(0,1) == strArr[j + 1].substring(0,1)){
if(strArr [j].substring(1,2) > strArr[j + 1].substring(1,2)){
var temp = strArr[j + 1];
strArr[j + 1] = strArr[j];
strArr[j] = temp;
}
}*/
compareToIndexValue(strArr,compareInt,j);
count ++ ;
}
}
/*console.log("遍历次数:"+count);*/
/*console.log(strArr);*/
return strArr;
}
/**
* 根据首字母 排序,如果首字母相同则根据第二个字母排序...直到排出大小
*/
function compareToIndexValue(arr,int,arrIndex){
if(arr[arrIndex].substring(int,int+1) == arr[arrIndex + 1].substring(int,int+1)) compareToIndexValue(arr,int+1,arrIndex);//如果第一位相等,则继续比较第二个字符
else if(arr[arrIndex].substring(int,int+1) > arr[arrIndex + 1].substring(int,int+1)) {
var temp = arr[arrIndex + 1];
arr[arrIndex + 1] = arr[arrIndex];
arr[arrIndex] = temp
}/*else if(arr[arrIndex].substring(int,int+1) < arr[arrIndex + 1].substring(int,int+1)) return;*/
return;
}
/**
* 输入排序过后的key=value 值数组,用 "&" 字符拼接为字符串
*/
function getKeyValueSortStr(strArr){
var longStr = "";
for (var str in strArr) {
longStr += strArr[str] + "&";
}
return longStr.substring(0,longStr.length - 1);//移除最后一个 & 符号
}
我的调用过程
需要注意的是:jquery的serialize()方法,是序列化表单的,通常调用此方法后会直接请求给后台,因此此方法会将一些参数url编码化,会出现%开头的特殊符号和一些其他符号,需要转换成原始值才能签名正确
//实现本地化签名,不需要 在另外一个jsp 页面计算签名
function testMD2(){
var formParam = $("#bankPay").serialize();//获得参数的 key = value & key2 = value2形式
var paraArr = formParam.split("&");//获得key=value 形式值的数组
for(var i = 0;i < paraArr.length; i ++){
if(paraArr[i].indexOf("=") + 2 > paraArr[i].length){//移除value 为空的参数
paraArr.splice(i, 1);
i --;
}
}
var sortParaArr = getKeySort(paraArr);
var paraStr = getKeyValueSortStr(sortParaArr).replace(/\+/g," ").replace(/%3A/g,":");//得到字符串 , + 是特殊字符,需要转义符号 \
console.log(paraStr);
var sign = hex_md5(paraStr + priKey);
$("#sign").val(sign);
}
hex_md5 为md5.js 中的方法