WO+开放平台:API调用开发手记(关于签名字段)

来源:互联网 发布:任我行定位软件 编辑:程序博客网 时间:2024/05/16 12:18

上篇讨论了『计费能力2.0版』的使用,对于第二个API『按次类支付接口』我没有展开,原本以为可以举一反三,但事实上,有个字段signature 却不是那么容易反出来的。

所以,我补充说明一下这个字段值的生成,代码同样参考我放在gitHub上的工程。

A)文档研读

来看这个API,有请求消息中有两个字段需要注意的,一是signType,签名类型,文档要求我们直接填写『HMAC-SHA1』,这是因为WO+平台暂只支持这一种签名算法。第二是signature,文档的描述是:

除signType和signature外,将post中的参数,所有参数按key进行字典升序排列,排序后的参数(key=value)用&拼接起来,生成待签名字符串。signature= base64_encode(签名算法("sha1",$待签名字符串, $(appKey&appSecret), true))。

还是很好理解,不过有个坑要注意,这里的排序是忽略大小写的。

好吧,我们的方案也出来了,将原来的参数Map转换成TreeMap,然后利用它的排序功能输出并拼装一个字符串(Key1=Value1&Key2=Value2)。再利用J2SE中自带的安全包实现HMAC的签名算法。


B)编写代码


方案有了,代码也就有了。可以参考gitHub中那个工程的EMCSign类。

public static String signValue(HashMap<String,Object> params,String secretKey){String password=null;TreeMap<String,Object> tmap = new TreeMap<String,Object>(new Comparator<String>(){                        //<span style="color:#009900;">注意,我们Key的排序是忽略大小写的</span>public int compare(String k1, String k2) {// TODO Auto-generated method stubreturn k1.toLowerCase().compareTo(k2.toLowerCase());}});tmap.putAll(params);try {StringBuilder sb=new StringBuilder();for(Object key :tmap.keySet()){sb.append("&");sb.append(key);sb.append("=");sb.append(tmap.get(key));}String signStr = sb.toString();String source = checkMsgDigest(signStr.substring(1), secretKey);password = source;       } catch (Exception e) {      e.printStackTrace(); } return password;}

上述代码演示了从Map到TreeMap再拼出要签名的字符串的过程。再看它调用的那个方法 checkMsgDigest。

static String CRYPTO_NAME_HMAC_SHA1 = "HmacSHA1";static byte[] getByte(String source, String secretKey)throws NoSuchAlgorithmException, InvalidKeyException {try {SecretKeySpec secret = new SecretKeySpec(secretKey.getBytes(),CRYPTO_NAME_HMAC_SHA1);Mac mac = Mac.getInstance(CRYPTO_NAME_HMAC_SHA1);mac.init(secret);byte[] result = mac.doFinal(source.getBytes("UTF-8"));return result;} catch (Exception e) {e.printStackTrace();return null;} }static String checkMsgDigest(String sourceStr,String secretKey) throws InvalidKeyException, NoSuchAlgorithmException {byte[] msgBase64Digest;byte[] tmpEncrypted = getByte(sourceStr, secretKey);msgBase64Digest = Base64.encodeBase64(tmpEncrypted);String passWord = null;try {passWord = new String(msgBase64Digest, "UTF-8");} catch (UnsupportedEncodingException e) {e.printStackTrace();}return passWord;}

这两个方法真没啥可说了,网上现成的。就是用HmacSHA1算法,用appSecret作密钥,对传入的字符串签名,编码为UTF-8。


至此,signature的值也就就绪了。

现在,你可以真正的举一反三了。


0 0
原创粉丝点击