最近公司使用nodejs调用阿里云短信接口发送短信,网上找了很多示例都不行,给的那些都不能正常使用。下面给出我调用成功的示例。
阿里云短信调用实质上就是构建一个http请求可以是post也可以是get,关键几个位置是域名、调用的方法,参数等几个东西,这几个东西对了以后调用就成功。
首先是域名,阿里云短信域名为http://dysmsapi.aliyuncs.com/,
之后是对应的参数,其它的参数都是比较简单的,关键的参数是Signature,Signature是签名参数,这个参数是根据构建的参数列表生成的,并且是唯一,每次调用都要重新生成。
第一步需要将对应的参数按着规则转为URI,第二步将URI使用hmac-sha1加密,然后转为base64第三步替换对应的特殊符合(这步有坑)。
第一步中需要注意的是Timestamp必须是东八区时区,不然会报过期的Timestamp参数、参数必须排序。第二步是调用系统内置的Hmac-sha1算法加密,没有啥注意的,顺序不错就好了。第三步,官网是把 + 替换成 %20,* 替换成 %2A,%7E替换成 ~,我替换+ 后会报签名算法不对,不知是不是算法规则改了。
下面给出具体示例:
var uuid = require('node-uuid');
var crypto = require('crypto');
var moment = require('moment');
var http = require('http');
var alidayuUrl = 'http://dysmsapi.aliyuncs.com/';
var OPAPI = require('opapi');
var config = {
AppKey: 'your keyID',
AppSecret: 'your keySecret'
};
var obj = {
AccessKeyId: config.AppKey,
Action: 'SendSms',
Format: 'JSON',
PhoneNumbers: '',
RegionId: 'cn-hangzhou',
SignName: '麦杰科技',
SignatureMethod: 'HMAC-SHA1',
SignatureNonce: uuid.v1(),
SignatureVersion: '1.0',
TemplateCode: 'SMS_78610022',
TemplateParam: '{"code":"123456"}',
Timestamp: '',
Version: '2017-05-25'
}
var sms = {
NORMAL_TEMPPLATE: 'SMS_78770029',
REGISTER_TEMPLATE: 'SMS_75995228',
CHANGEPROJECT_TEMPLATE: 'SMS_75995226',
FORGETPASSS_TEMPLATE: 'SMS_75995225',
sendMessage: function (phone, TemplateCode, TemplateParam, callback) {
var sendurl = this.url(phone, TemplateCode, TemplateParam);
var req = http.request(sendurl, function (res) {
var status = res.statusCode;
if (status != 200) {
callback(new Error('网络异常'));
}
res.setEncoding('utf8');
res.on('data', function (chunk) {
var value = JSON.parse(chunk);
if (value.Code != 'OK') {
console.log(chunk);
callback(new Error('短信发送异常'));
} else {
callback(null);
}
}).on('error', function (e) {
callback(new Error('发送短信异常'));
});
});
req.write('执行完毕');
req.end();
},
sign: function (params, accessSecret) {
var param = {}, qstring = [];
var oa = Object.keys(params);
for (var i = 0; i < oa.length; i++) {
param[oa[i]] = params[oa[i]];
}
for (var key in param) {
qstring.push(encodeURIComponent(key) + '=' + encodeURIComponent(param[key]));
}
qstring = qstring.join('&');
var StringToSign = 'GET' + '&' + encodeURIComponent('/') + '&' + encodeURIComponent(qstring);
accessSecret = accessSecret + '&';
var signature = crypto.createHmac('sha1', accessSecret).update(StringToSign).digest().toString('base64');
signature = signature.replace(/\*/, '%2A').replace(/%7E/, '~');
return signature;
},
url: function (phone, TemplateCode, TemplateParam) {
var timestamp = moment(new Date().getTime() - 3600 * 1000 * 8).format("YYYY-MM-DDTHH:mm:ss") + 'Z';
obj.PhoneNumbers = phone;
obj.SignatureNonce = uuid.v1();
obj.TemplateCode = TemplateCode;
obj.TemplateParam = TemplateParam;
obj.Timestamp = timestamp;
var sign = this.sign(obj, config.AppSecret);
var arr = [];
for (var p in obj) {
arr.push(encodeURIComponent(p) + '=' + encodeURIComponent(obj[p]));
}
arr.push(encodeURIComponent('Signature') + '=' + encodeURIComponent(sign))
var msg = arr.join('&')
var sendurl = alidayuUrl + '?' + msg;
return sendurl;
}
}
module.exports = sms;
上面的示例是今天刚跑通的示例,使用的时候只需要替换自己的对应的签名信息,模板编码等信息就可以。需要注意的地方已经在上面说了,如有不懂的地方可以留言。
https://help.aliyun.com/document_detail/56189.html?spm=5176.doc55288.6.562.D2yUYz
这个是阿里云官方给的解释和java生成签名的过程,其中的坑已经在上面说明了。
特别提示 参数排序,东八区时间,特殊字符替换