Delphi调用腾讯云最新签名方法v3 TC3-HMAC-SHA256发送短信

博客介绍了如何在Delphi中调用腾讯云最新的TC3-HMAC-SHA256 v3签名方法来发送短信。通过创建独立的TC3鉴权单元文件,简化了鉴权过程,便于代码复用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

参考了高文杰先生的代码,结合自己的学习增添了最新TC3-HMAC-SHA256 v3版本的接口。

 腾讯云的TC3 v3鉴权比较复杂,当然这是相对于Delphi下而言,其实在Python下直接使用SDK要省事儿的多。本文的源代码就不贴了,需要的可以去原文下载。

一、TC3鉴权单元

为了方便复用,写了一个TC3鉴权单元文件:TC3_Authorization.pas

{
2021-02-15
广西南宁
张旭州
腾讯云 TC3-HMAC-SHA256 生成鉴权数据
}

unit TC3_Authorization;

interface

uses
  System.SysUtils, System.hash, System.NetEncoding, System.DateUtils;

{ -------------------------------------------------------------------------------
  过程名:    genTC3Auth
  作者:      张旭州
  日期:      2021.02.15
  参数:      SecretKey, SecretId, sDomain, bodyJSON, Service: string
  参数说明: AccessKeyID,AccessKeySecret,域名, 待发送的数据主体JSON, 服务ocr, cvm
  返回值:    string
  
  参数参考如下:
    SecretKey := '您的腾讯云SecretKey';
    SecretId := '您的腾讯云SecretId';
    Service := 'sms'  //发送短信
    sDomain := 'sms.tencentcloudapi.com'   //短信发送的域名

  ------------------------------------------------------------------------------- }
function genTC3Auth(SecretKey, SecretId, sDomain, bodyJSON, Service: string): string;

implementation


function DateTimeToUnix(const AValue: TDateTime): Int64;
// 日期转Unix时间戳
begin
  Result := System.DateUtils.DateTimeToUnix(AValue) - 8 * 60 * 60;
end;

//腾讯云TC3 V3签名鉴权
function genTC3Auth(SecretKey, SecretId, sDomain, bodyJSON, Service: string): string;
var
  httpRequestMethod: string; // = "POST";
  canonicalUri: string; //= "/";
  canonicalQueryString: string; //= "";
  canonicalHeaders: string; // = "content-type:application/json; charset=utf-8\n" + "host:" + host + "\n";
  signedHeaders: string; //= "content-type;host";
  SecretDate, SecretService, SecretSigning, Signature: TBytes;
  StringToSign, payload, CanonicalRequest, HashedRequestPayload, HashedCanonicalRequest: string;
  sDate,timestamp : string;
  Authorization, CredentialScope : string;
begin
  sDate := FormatDateTime('YYYY-MM-DD', now());
  timestamp := DateTimeToUnix(now).ToString;
  httpRequestMethod := 'POST';
  canonicalUri := '/';
  canonicalQueryString := '';
  canonicalHeaders := 'content-type:application/json' + #10
      + 'host:' + sDomain + #10;
  signedHeaders := 'content-type;host';

  payload := bodyJSON;
  //待发送的数据的哈希值:
  HashedRequestPayload := THashSHA2.GetHashString(payload);

  //拼接规范请求串
  CanonicalRequest := httpRequestMethod + #10
      + canonicalUri + #10
      + canonicalQueryString + #10
      + canonicalHeaders + #10
      + signedHeaders + #10
      + HashedRequestPayload;

  //计算派生签名密钥
  SecretDate := THashSHA2.GetHMACAsBytes(sDate, TEncoding.utf8.GetBytes('TC3' + SecretKey));
  SecretService := THashSHA2.GetHMACAsBytes(Service, SecretDate);
  SecretSigning := THashSHA2.GetHMACAsBytes('tc3_request', SecretService);

  //规范请求串的哈希值
  HashedCanonicalRequest := THashSHA2.GetHashString(CanonicalRequest);
  //组装待签名字符串
  StringToSign := 'TC3-HMAC-SHA256' + #10
      + timestamp + #10
      + sDate + '/' + Service + '/tc3_request' + #10
      + HashedCanonicalRequest;
  //计算签名
  Signature := THashSHA2.GetHMACAsBytes(Bytesof(StringToSign), SecretSigning);
//  Application.MessageBox(PChar(THash.DigestAsString(Signature)),
//      '提示', MB_OK + MB_ICONINFORMATION + MB_TOPMOST);

  CredentialScope := sDate + '/' + Service + '/tc3_request';
  //拼接 Authorization
  Authorization :=
    'TC3-HMAC-SHA256' + ' ' +
    'Credential=' + SecretId + '/' + CredentialScope + ', ' +
    'SignedHeaders=' + SignedHeaders + ', ' +
    'Signature=' + StringReplace(PChar(THash.DigestAsString(Signature)), Chr(13) + Chr(10), '',
    [rfReplaceAll]);

  Result := Authorization;
end;

end.

二、短信发送模块

在implementation下 uses
 Unit2, TC3_Authorization;

procedure TForm1.btn_tc3_sendClick(Sender: TObject);
var
  strMobile, SecretKey, SecretId,sdkappid,sign, params, tpl_id, strjson:string;
  tc3 : string;
  url : string;
  http : TIdHTTP;
  jsonToSend : TStringStream;
  Aresult:string;
  //申明变量
  Root:TJSONObject;    //uses System.JSON;
  jsonArray: TJSONArray; // JSON数组变量
  list : TStringList;
  i : Integer;
  phoneSet : string;

begin
  list := TStringList.Create;
  list.CommaText := edt_strMobile.Text;
  for i := 0 to list.Count -1  do
  begin
    phoneSet := phoneSet + '"86' + list[i] + '",'
  end;

  strMobile := phoneSet.Remove(Length(phoneSet)-1);
  list.Free;

  SecretKey := '您的Key';
  SecretId := '您的ID';
  sdkappid := edt_sdkappid.Text;
  sign := edt_sign.Text;
  params := edt_params.Text;
  tpl_id := edt_tpl_id.Text;

  strjson := '{'
  + '"PhoneNumberSet":['
  + strMobile
  + '],'
  + '"TemplateParamSet":' + params
  + ','
  + '"TemplateID":"'
  + tpl_id
  + '",'
  + '"SmsSdkAppid":"'
  + sdkappid
  + '",'
  + '"Sign":"'
  + sign
  +'"}';

  tc3 := TC3_Authorization.genTC3Auth(SecretKey, SecretId, 'sms.tencentcloudapi.com',
     strjson, 'sms');
  url := 'https://sms.tencentcloudapi.com/';
  http := TIdHttp.Create(nil);
  http.HandleRedirects := True;
  http.ReadTimeout := 3000;
  http.Request.ContentType := 'application/json';//设置内容类型为json

  jsonToSend := TStringStream.Create(strjson, TEncoding.UTF8);
  jsonToSend.Position := 0;//将流位置置为0
  http.Request.CustomHeaders.Clear;
  http.Request.CustomHeaders.AddValue('Authorization', ' ' + tc3);
  http.Request.CustomHeaders.AddValue('Content-Type', ' application/json');
  http.Request.CustomHeaders.AddValue('Host', ' sms.tencentcloudapi.com');
  http.Request.CustomHeaders.AddValue('X-TC-Action', ' SendSms');
  http.Request.CustomHeaders.AddValue('X-TC-Timestamp', ' ' + gwj_DateTimeToUnix(now).ToString);
  http.Request.CustomHeaders.AddValue('X-TC-Version', ' 2019-07-11');

  http.Request.AcceptCharSet := 'UTF-8';
  http.Request.AcceptEncoding := 'UTF-8';
  http.Request.AcceptLanguage := 'UTF-8';
  http.Request.CharSet := 'UTF-8';
//  http.HTTPOptions := IdHTTP.HTTPOptions + [hoKeepOrigProtocol];

  Aresult := http.Post(url, jsonToSend);//用MEMO控件接收POST后的数据返回
  Aresult := UnicodeToChinese(Aresult);
  Memo1.Text := Aresult;
  jsonToSend.free;
  http.free;

  //发送成功的示例
  //{"Response":{"SendStatusSet":[{"SerialNo":"2019:2892974270720676287","PhoneNumber":"+8613377131696","Fee":1,"SessionContext":"","Code":"Ok","Message":"send success","IsoCode":"CN"}],"RequestId":"b2e1fdcb-e877-4bbe-89cc-e7cae7cb567d"}}

  Root:= TJSONObject.ParseJSONValue(Trim(Aresult)) as TJSONObject;   //uses System.JSON;
  Root := Root.GetValue('Response') as TJSONObject;
  jsonArray := Root.GetValue('SendStatusSet') as TJSONArray ;

  Root := jsonArray.Get(0) as TJSONObject; //第一个号码结果

  edt_result.Text := Root.GetValue('Code').Value;
  edt_errmsg.Text := Root.GetValue('Message').Value;
  edt_ext.Text := Root.GetValue('SessionContext').Value;
end;

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值