相关资料:
https://blog.csdn.net/hsuzo1/article/details/113823621
一、TC3鉴权单元
为了方便复用,写了一个TC3鉴权单元文件:TC3_Authorization.pas
1 { 2 2021-02-15 3 广西南宁 4 张旭州 5 腾讯云 TC3-HMAC-SHA256 生成鉴权数据 6 } 7 8 unit TC3_Authorization; 9 10 interface 11 12 uses 13 System.SysUtils, System.hash, System.NetEncoding, System.DateUtils; 14 15 { ------------------------------------------------------------------------------- 16 过程名: genTC3Auth 17 作者: 张旭州 18 日期: 2021.02.15 19 参数: SecretKey, SecretId, sDomain, bodyJSON, Service: string 20 参数说明: AccessKeyID,AccessKeySecret,域名, 待发送的数据主体JSON, 服务ocr, cvm 21 返回值: string 22 23 参数参考如下: 24 SecretKey := '您的腾讯云SecretKey'; 25 SecretId := '您的腾讯云SecretId'; 26 Service := 'sms' //发送短信 27 sDomain := 'sms.tencentcloudapi.com' //短信发送的域名 28 ------------------------------------------------------------------------------- } 29 function genTC3Auth(SecretKey, SecretId, sDomain, bodyJSON, Service: string): string; 30 31 implementation 32 33 34 function DateTimeToUnix(const AValue: TDateTime): Int64; 35 // 日期转Unix时间戳 36 begin 37 Result := System.DateUtils.DateTimeToUnix(AValue) - 8 * 60 * 60; 38 end; 39 40 //腾讯云TC3 V3签名鉴权 41 function genTC3Auth(SecretKey, SecretId, sDomain, bodyJSON, Service: string): string; 42 var 43 httpRequestMethod: string; // = "POST"; 44 canonicalUri: string; //= "/"; 45 canonicalQueryString: string; //= ""; 46 canonicalHeaders: string; // = "content-type:application/json; charset=utf-8 " + "host:" + host + " "; 47 signedHeaders: string; //= "content-type;host"; 48 SecretDate, SecretService, SecretSigning, Signature: TBytes; 49 StringToSign, payload, CanonicalRequest, HashedRequestPayload, HashedCanonicalRequest: string; 50 sDate,timestamp : string; 51 Authorization, CredentialScope : string; 52 begin 53 sDate := FormatDateTime('YYYY-MM-DD', now()); 54 timestamp := DateTimeToUnix(now).ToString; 55 httpRequestMethod := 'POST'; 56 canonicalUri := '/'; 57 canonicalQueryString := ''; 58 canonicalHeaders := 'content-type:application/json' + #10 59 + 'host:' + sDomain + #10; 60 signedHeaders := 'content-type;host'; 61 62 payload := bodyJSON; 63 //待发送的数据的哈希值: 64 HashedRequestPayload := THashSHA2.GetHashString(payload); 65 66 //拼接规范请求串 67 CanonicalRequest := httpRequestMethod + #10 68 + canonicalUri + #10 69 + canonicalQueryString + #10 70 + canonicalHeaders + #10 71 + signedHeaders + #10 72 + HashedRequestPayload; 73 74 //计算派生签名密钥 75 SecretDate := THashSHA2.GetHMACAsBytes(sDate, TEncoding.utf8.GetBytes('TC3' + SecretKey)); 76 SecretService := THashSHA2.GetHMACAsBytes(Service, SecretDate); 77 SecretSigning := THashSHA2.GetHMACAsBytes('tc3_request', SecretService); 78 79 //规范请求串的哈希值 80 HashedCanonicalRequest := THashSHA2.GetHashString(CanonicalRequest); 81 //组装待签名字符串 82 StringToSign := 'TC3-HMAC-SHA256' + #10 83 + timestamp + #10 84 + sDate + '/' + Service + '/tc3_request' + #10 85 + HashedCanonicalRequest; 86 //计算签名 87 Signature := THashSHA2.GetHMACAsBytes(Bytesof(StringToSign), SecretSigning); 88 // Application.MessageBox(PChar(THash.DigestAsString(Signature)), 89 // '提示', MB_OK + MB_ICONINFORMATION + MB_TOPMOST); 90 91 CredentialScope := sDate + '/' + Service + '/tc3_request'; 92 //拼接 Authorization 93 Authorization := 94 'TC3-HMAC-SHA256' + ' ' + 95 'Credential=' + SecretId + '/' + CredentialScope + ', ' + 96 'SignedHeaders=' + SignedHeaders + ', ' + 97 'Signature=' + StringReplace(PChar(THash.DigestAsString(Signature)), Chr(13) + Chr(10), '', 98 [rfReplaceAll]); 99 100 Result := Authorization; 101 end; 102 103 end.
二、短信发送模块
在implementation下 uses
Unit2, TC3_Authorization;
1 procedure TForm1.btn_tc3_sendClick(Sender: TObject); 2 var 3 strMobile, SecretKey, SecretId,sdkappid,sign, params, tpl_id, strjson:string; 4 tc3 : string; 5 url : string; 6 http : TIdHTTP; 7 jsonToSend : TStringStream; 8 Aresult:string; 9 //申明变量 10 Root:TJSONObject; //uses System.JSON; 11 jsonArray: TJSONArray; // JSON数组变量 12 list : TStringList; 13 i : Integer; 14 phoneSet : string; 15 16 begin 17 list := TStringList.Create; 18 list.CommaText := edt_strMobile.Text; 19 for i := 0 to list.Count -1 do 20 begin 21 phoneSet := phoneSet + '"86' + list[i] + '",' 22 end; 23 24 strMobile := phoneSet.Remove(Length(phoneSet)-1); 25 list.Free; 26 27 SecretKey := '您的Key'; 28 SecretId := '您的ID'; 29 sdkappid := edt_sdkappid.Text; 30 sign := edt_sign.Text; 31 params := edt_params.Text; 32 tpl_id := edt_tpl_id.Text; 33 34 strjson := '{' 35 + '"PhoneNumberSet":[' 36 + strMobile 37 + '],' 38 + '"TemplateParamSet":' + params 39 + ',' 40 + '"TemplateID":"' 41 + tpl_id 42 + '",' 43 + '"SmsSdkAppid":"' 44 + sdkappid 45 + '",' 46 + '"Sign":"' 47 + sign 48 +'"}'; 49 50 tc3 := TC3_Authorization.genTC3Auth(SecretKey, SecretId, 'sms.tencentcloudapi.com', 51 strjson, 'sms'); 52 url := 'https://sms.tencentcloudapi.com/'; 53 http := TIdHttp.Create(nil); 54 http.HandleRedirects := True; 55 http.ReadTimeout := 3000; 56 http.Request.ContentType := 'application/json';//设置内容类型为json 57 58 jsonToSend := TStringStream.Create(strjson, TEncoding.UTF8); 59 jsonToSend.Position := 0;//将流位置置为0 60 http.Request.CustomHeaders.Clear; 61 http.Request.CustomHeaders.AddValue('Authorization', ' ' + tc3); 62 http.Request.CustomHeaders.AddValue('Content-Type', ' application/json'); 63 http.Request.CustomHeaders.AddValue('Host', ' sms.tencentcloudapi.com'); 64 http.Request.CustomHeaders.AddValue('X-TC-Action', ' SendSms'); 65 http.Request.CustomHeaders.AddValue('X-TC-Timestamp', ' ' + gwj_DateTimeToUnix(now).ToString); 66 http.Request.CustomHeaders.AddValue('X-TC-Version', ' 2019-07-11'); 67 68 http.Request.AcceptCharSet := 'UTF-8'; 69 http.Request.AcceptEncoding := 'UTF-8'; 70 http.Request.AcceptLanguage := 'UTF-8'; 71 http.Request.CharSet := 'UTF-8'; 72 // http.HTTPOptions := IdHTTP.HTTPOptions + [hoKeepOrigProtocol]; 73 74 Aresult := http.Post(url, jsonToSend);//用MEMO控件接收POST后的数据返回 75 Aresult := UnicodeToChinese(Aresult); 76 Memo1.Text := Aresult; 77 jsonToSend.free; 78 http.free; 79 80 //发送成功的示例 81 //{"Response":{"SendStatusSet":[{"SerialNo":"2019:2892974270720676287","PhoneNumber":"+8613377131696","Fee":1,"SessionContext":"","Code":"Ok","Message":"send success","IsoCode":"CN"}],"RequestId":"b2e1fdcb-e877-4bbe-89cc-e7cae7cb567d"}} 82 83 Root:= TJSONObject.ParseJSONValue(Trim(Aresult)) as TJSONObject; //uses System.JSON; 84 Root := Root.GetValue('Response') as TJSONObject; 85 jsonArray := Root.GetValue('SendStatusSet') as TJSONArray ; 86 87 Root := jsonArray.Get(0) as TJSONObject; //第一个号码结果 88 89 edt_result.Text := Root.GetValue('Code').Value; 90 edt_errmsg.Text := Root.GetValue('Message').Value; 91 edt_ext.Text := Root.GetValue('SessionContext').Value; 92 end;