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

上篇讨论了『计费能力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 stub
				return 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的值也就就绪了。

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


你可能感兴趣的:(api,安全,开放平台)