Java版:
package com.mmall.test;
/**
* 阿里云短信http发送url构造
* https://help.aliyun.com/document_detail/56189.html?spm=a2c4g.11186623.6.590.7cfdB8hhB8hhtr
* @author Declan
*/
public class SignDemo {
public static void main(String[] args) throws Exception {
String accessKeyId = "xxxxxxxxxxxxxxxxxx";
String accessSecret = "xxxxxxxxxxxxxxxxxxxxx";
java.text.SimpleDateFormat df = new java.text.SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
df.setTimeZone(new java.util.SimpleTimeZone(0, "GMT"));// 这里一定要设置GMT时区
java.util.Map<String, String> paras = new java.util.HashMap();
// 1. 系统参数
paras.put("SignatureMethod", "HMAC-SHA1");
paras.put("SignatureNonce", java.util.UUID.randomUUID().toString());
paras.put("AccessKeyId", accessKeyId);
paras.put("SignatureVersion", "1.0");
paras.put("Timestamp", df.format(new java.util.Date()));
paras.put("Format", "XML");
// 2. 业务API参数
paras.put("Action", "SendSms");
paras.put("Version", "2017-05-25");
paras.put("RegionId", "cn-hangzhou");
paras.put("PhoneNumbers", "13800138000");
paras.put("SignName", "上海东方明珠");
paras.put("TemplateParam", "{\"code\":\"1234\"}");
paras.put("TemplateCode", "SMS_144405431");
// paras.put("TemplateCode", "SMS_0000");
// paras.put("OutId", "123");
// 3. 去除签名关键字Key
if (paras.containsKey("Signature"))
paras.remove("Signature");
// 4. 参数KEY排序
java.util.TreeMap<String, String> sortParas = new java.util.TreeMap<String, String>();
sortParas.putAll(paras);
// 5. 构造待签名的字符串
java.util.Iterator<String> it = sortParas.keySet().iterator();
StringBuilder sortQueryStringTmp = new StringBuilder();
while (it.hasNext()) {
String key = it.next();
sortQueryStringTmp.append("&").append(specialUrlEncode(key)).append("=").append(specialUrlEncode(paras.get(key)));
}
// 去除第一个多余的&符号
String sortedQueryString = sortQueryStringTmp.substring(1);
StringBuilder stringToSign = new StringBuilder();
stringToSign.append("GET").append("&");
stringToSign.append(specialUrlEncode("/")).append("&");
stringToSign.append(specialUrlEncode(sortedQueryString));
String sign = sign(accessSecret + "&", stringToSign.toString());
// 6. 签名最后也要做特殊URL编码
String signature = specialUrlEncode(sign);
// System.out.println(paras.get("SignatureNonce"));
// System.out.println("\r\n=========\r\n");
// System.out.println(paras.get("Timestamp"));
// System.out.println("\r\n=========\r\n");
// System.out.println(sortedQueryString);
// System.out.println("\r\n=========\r\n");
// System.out.println(stringToSign.toString());
// System.out.println("\r\n=========\r\n");
// System.out.println(sign);
// System.out.println("\r\n=========\r\n");
// System.out.println(signature);
// System.out.println("\r\n=========\r\n");
// 最终打印出合法GET请求的URL
System.out.println("http://dysmsapi.aliyuncs.com/?Signature=" + signature + sortQueryStringTmp);
}
public static String specialUrlEncode(String value) throws Exception {
return java.net.URLEncoder.encode(value, "UTF-8").replace("+", "%20").replace("*", "%2A").replace("%7E", "~");
}
public static String sign(String accessSecret, String stringToSign) throws Exception {
javax.crypto.Mac mac = javax.crypto.Mac.getInstance("HmacSHA1");
mac.init(new javax.crypto.spec.SecretKeySpec(accessSecret.getBytes("UTF-8"), "HmacSHA1"));
byte[] signData = mac.doFinal(stringToSign.getBytes("UTF-8"));
//gmK7se8XVpMA+6h+E33NG8ADk7E=
return new sun.misc.BASE64Encoder().encode(signData);
}
}
Python 版
# coding:utf-8
import sys
reload(sys)
sys.setdefaultencoding('utf-8')
from datetime import datetime
import uuid
from urllib import quote
from hashlib import sha1
import hmac
from hmac import new as hmac
def specialUrlEncode(value):
newValue = quote(str(value).encode('utf-8'), safe='').replace('+', '%20').replace('*', '%2A').replace('%7E', '~')
return newValue
def sign(accessSecret, stringToSign):
return str(hmac(accessSecret, stringToSign, sha1).digest().encode('base64')[:-1])
def generateALiYunSmsUrl():
accessKeyId = "xxxxxxxxxxx"
accessSecret = "xxxxxxxxxxxxxxxxxxxxxxxxx"
time_format_str = datetime.utcnow().isoformat()
time_format_str = time_format_str.split(".")[0] + "Z"
dic = {}
dic["SignatureMethod"]="HMAC-SHA1"
# uuid
dic["SignatureNonce"]=str(uuid.uuid1())
dic["AccessKeyId"] = accessKeyId
dic["SignatureVersion"] = "1.0"
dic["Timestamp"] = time_format_str
dic["Format"] = "XML"
# 业务API参数
dic["Action"] = "SendSms"
dic["Version"] = "2017-05-25"
dic["RegionId"] = "cn-hangzhou"
dic["PhoneNumbers"] = "13800138000"
dic["SignName"] = "上海东方明珠"
dic["TemplateParam"] = "{'code':'1234'}"
dic["TemplateCode"] = "SMS_144405431"
# 如果字典中有 Signature 则将其去除掉
if dic.has_key("Signature"):
dic.pop("Signature")
# 构造一个list,将dic中的key放在list中,并对list进行升序排序
list = []
for key in dic:
list.append(key)
# 进行排序
list.sort()
sortQueryStringTmp = ''
for key in list:
sortQueryStringTmp = sortQueryStringTmp + '&' + specialUrlEncode(key)+'='+specialUrlEncode(dic[key])
# 去掉第一个 '&'
sortQueryString = sortQueryStringTmp[1:]
#构造签名 (这里对 '/' 也要进行编码 )
stringToSign = 'GET'+'&'+quote('/', safe='')+'&'
stringToSign = stringToSign+specialUrlEncode(sortQueryString)
#进行签名加密
privateSign = sign(accessSecret+'&', stringToSign)
#签名最后做特殊URL处理
signature = specialUrlEncode(privateSign)
# 得到的发送短信的url
print "http://dysmsapi.aliyuncs.com/?Signature="+signature+sortQueryStringTmp
generateALiYunSmsUrl()