目录
Delphi开发短信应用-阿里云服务
以此文作为参考,开发者可以开发任何云平台上V3版的Rest API接口的服务应用。
一、阿里云短信、语音、流量API接口
云通信下的三类产品(包括短信、语音、流量),Rest API接口协议一致:
https://help.aliyun.com/document_detail/56189.html?spm=a2c4g.11186623.6.670.f3786220T5zc4h
1.1、入参列表
短信Rest请求参数:
如HTTP示例包中,请求的参数可以分两大块:系统参数和业务参数。
系统参数为POP协议的基本参数:
参数KEY | 是否必填 | 说明 |
---|---|---|
AccessKeyId | 是 | |
Timestamp | 是 | 格式为:yyyy-MM-dd'T'HH:mm:ss'Z';时区为:GMT |
Format | 否 | 没传默认为JSON,可选填值:XML |
SignatureMethod | 是 | 建议固定值:HMAC-SHA1 |
SignatureVersion | 是 | 建议固定值:1.0 |
SignatureNonce | 是 | 用于请求的防重放攻击,每次请求唯一,JAVA语言建议用:java.util.UUID.randomUUID()生成即可 |
Signature | 是 | 最终生成的签名结果值 |
业务参数:
参数KEY | 是否必填 | 说明 |
---|---|---|
Action | 是 | API的命名,固定值,如发送短信API的值为:SendSms |
Version | 是 | API的版本,固定值,如短信API的值为:2017-05-25 |
RegionId | 是 | API支持的RegionID,如短信API的值为:cn-hangzhou |
PhoneNumbers | 是 | 具体见API文档描述 |
SignName | 是 | 具体见API文档描述 |
TemplateCode | 是 | 具体见API文档描述 |
TemplateParam | 否 | 具体见API文档描述 |
OutId | 否 | 具体见API文档描述 |
短信输入参数:
参数名称 | 参数类型 | 必填与否 | 样例取值 | 参数说明 |
---|---|---|---|---|
PhoneNumbers | String | 必须 | 15000000000 | 短信接收号码。支持以逗号分隔的形式进行批量调用,批量上限为1000个手机号码,批量调用相对于单条调用及时性稍有延迟,验证码类型的短信推荐使用单条调用的方式,发送国际/港澳台消息时,接收号码格式为:国际区号+号码,如“85200000000”。 |
SignName | String | 必须 | 云通信 | 短信签名。 |
TemplateCode | String | 必须 | SMS_0000 | 短信模板ID,发送国际/港澳台消息时,请使用国际/港澳台短信模版。 |
TemplateParam | String | 可选 | {"code":"1234","product":"ytx"} | 短信模板变量替换JSON串,友情提示:如果JSON中需要带换行符,请参照标准的JSON协议要求。 |
OutId | String | 可选 | abcdefgh | 外部流水扩展字段。 |
1.2、出参列表
出参名称 | 出参类型 | 样例取值 | 参数说明 |
---|---|---|---|
RequestId | String | 8906582E-6722 | 请求ID。 |
Code | String | OK | 状态码。返回OK代表请求成功,其他错误码详见错误码列表。 |
Message | String | 请求成功 | 状态码的描述。 |
BizId | String | 134523^4351232 | 发送回执ID,可根据该ID查询具体的发送状态。 |
1.3、Rest响应错误码列表
Code | 描述 |
---|---|
OK | 请求成功。 |
isp.RAM_PERMISSION_DENY | RAM权限DENY。 |
isv.OUT_OF_SERVICE | 业务停机。 |
isv.PRODUCT_UN_SUBSCRIPT | 未开通云通信产品的阿里云客户。 |
isv.PRODUCT_UNSUBSCRIBE | 产品未开通。 |
isv.ACCOUNT_NOT_EXISTS | 账户不存在。 |
isv.ACCOUNT_ABNORMAL | 账户异常。 |
isv.SMS_TEMPLATE_ILLEGAL | 短信模板不合法。 |
isv.SMS_SIGNATURE_ILLEGAL | 短信签名不合法。 |
isv.INVALID_PARAMETERS | 参数异常。 |
isp.SYSTEM_ERROR | 系统错误。 |
isv.MOBILE_NUMBER_ILLEGAL | 非法手机号。 |
isv.MOBILE_COUNT_OVER_LIMIT | 手机号码数量超过限制。 |
isv.TEMPLATE_MISSING_PARAMETERS | 模板缺少变量。 |
isv.BUSINESS_LIMIT_CONTROL | 业务限流。 |
isv.INVALID_JSON_PARAM | JSON参数不合法,只接受字符串值。 |
isv.BLACK_KEY_CONTROL_LIMIT | 黑名单管控。 |
isv.PARAM_LENGTH_LIMIT | 参数超出长度限制。 |
isv.PARAM_NOT_SUPPORT_URL | 不支持URL。 |
isv.AMOUNT_NOT_ENOUGH | 账户余额不足。 |
1.4、基于Node.js的SDK代码demo参考及说明
https://help.aliyun.com/document_detail/57458.html?spm=a2c4g.11186623.6.687.7e9e2e7ev2MlSn
二、Delphi实现阿里云短信的关键-签名算法的实现
阿里云短信的POP签名算法
https://help.aliyun.com/document_detail/56189.html?spm=a2c4g.11186623.6.670.f3786220T5zc4h
见其中的【2.3 生成签名】 的说明。签名是为了让请求合法,共分为五步:
2.1、第一步:请求参数:
请求参数包括系统参数和业务参数,不要遗漏
请求参数中不允许出现以Signature为key的参数。 参考代码如下:
var Params: TDictionary<string, string>; SortedParams: TArray<string>;
LParamIndex :Integer;
//①.系统参数:
Params.Add('AccessKeyId', AccessKeyId);
Params.Add('Timestamp', GetTimestamp);
Params.Add('Format', 'JSON');
Params.Add('SignatureMethod', 'HMAC-SHA1');
Params.Add('SignatureNonce',
THashMD5.GetHashString(TGUID.NewGuid.ToString));
Params.Add('SignatureVersion', '1.0');
//②.业务API参数:
Params.Add('Action', 'SendSms');
Params.Add('Version', '2017-05-25');
Params.Add('RegionId', 'cn-hangzhou');
Params.Add('PhoneNumbers', PhoneNumbers);
Params.Add('SignName', SignName);
Params.Add('TemplateCode', TemplateCode);
Params.Add('TemplateParam', TemplateParam);
Params.Add('OutId', '');
//③.去除签名关键字Key:
//2.1.3:(我加的严格按照API说明更安全)去除签名关键字Key:'Signature':
if Params.ContainsKey('Signature') then Params.Remove('Signature');
2.2、 第二步:根据参数Key排序(顺序):
//2.2、第二步:根据参数Key排序(顺序)::
SortedParams := Params.keys.ToArray;
TArray.Sort<string>(SortedParams);
2.3、 第三步:构造待签名的请求串:
构造待签名的请求串这里有两步动作:
2.3.1、POP的URL编码特殊字符替换
第1步,把排序后的各参数按顺序拼接成如下格式的字符串sortQueryString:
"&" specialUrlEncode(参数Key) + "=" + specialUrlEncode(参数值)
首先介绍下面会用到的特殊URL编码 这个是POP特殊的一种规则,即在一般的URLEncode后再增加三种字符替换:加号(+)替换成 %20、星号(*)替换成 %2A、%7E 替换回波浪号(~) 参考代码如下:
// POP的URL编码特殊字符替换参考代码如下:
function SpecialUrlEncode(const Value: string): string;
// SendVerificationCodeBySMS专用
begin
Result := TNetEncoding.URL.Encode(Value).Replace('+', '%20')
.Replace('*', '%2A').Replace('%7E', '~');
end;
2.3.2、拼接sortQueryString
sortQueryString:=''; LParamIndex:=0;
for Key in SortedParams do
begin
if LParamIndex=0 then
sortQueryString:=sortQueryString
+SpecialUrlEncode(Key)
+'='+SpecialUrlEncode(Params.Items[Key])
else
sortQueryString:=sortQueryString
+'&'+SpecialUrlEncode(Key)
+'='+SpecialUrlEncode(Params.Items[Key]);
INC(LParamIndex);
//:第1个参数不带连接符&
end;
2.4、 第四步:阿里云专用签名:
签名采用HmacSHA1算法 + Base64,编码采用:UTF-8 ,官方Java函数:
String sign = sign(accessSecret + "&", stringToSign.toString());
特别说明:POP要求需要后面多加一个“&
”字符,即accessSecret + “&”
2.4.1、Delphi的HmacSHA1算法函数
THashSHA1.GetHMACAsBytes
2.4.2、Delphi的Base64函数
TNetEncoding.Base64.EncodeBytesToString
2.4.3、构造阿里云专用Delphi签名函数
function Sign(const AData, Key: string): string;
var
HashBytes: TBytes;
begin
HashBytes := THashSHA1.GetHMACAsBytes(AData, Key);
Result := TNetEncoding.Base64.EncodeBytesToString(HashBytes);
end;
调用:
AcessSecret:你的AccessKeyId
对应的秘钥AccessSecret
Signature := Sign(sortQueryString,AccessKeySecret + '&');
签名后的结果类似打印如下:
zJDF+Lrzhj/ThnlvIToysFRq6t4=
2.5、 第五步:增加签名结果到请求参数中,发送请求:
注意 :上步骤最后一小步,签名也要做POP的URL编码特殊字符替换:
//String Signature = specialUrlEncode(sign);// zJDF%2BLrzhj%2FThnlvIToysFRq6t4%3D
:Delphi代码如下:
Signature := SpecialUrlEncode(Signature);
zJDF+Lrzhj/ThnlvIToysFRq6t4=
POP的URL编码特殊字符替换后:
zJDF%2BLrzhj%2FThnlvIToysFRq6t4%3D
签名完毕!
三、用Delphi通用Rest类及其方法发送阿里云短信
参考本博客博文:
《delphi Restful:客户端实现的四种方式及其比较》
喜欢的话,就在下面点个赞、收藏就好了,方便看下次的分享: