1
2use std::io::Error;
3use hex::encode;
4use hmac::{Hmac, Mac};
5use json::object;
6use sha2::{Digest, Sha256};
7
8#[derive(Clone, Debug)]
9pub struct Phone {
10 phone_number: Vec<String>,
12 sdk_appid: String,
14 templated_id: String,
16 sign_name: String,
18 secret_id: String,
20 secret_key: String,
22 templated_data: Vec<String>,
24
25}
26impl Phone {
27 pub fn new(phone_number: Vec<&str>, sdk_appid: &str, templated_id: &str, sign_name: &str,secret_id: &str,secret_key: &str,templated_data: Vec<&str>,) -> Self {
28 Self {
29 phone_number:phone_number.iter().map(|s| s.to_string()).collect(),
30 sdk_appid: sdk_appid.to_string(),
31 templated_id: templated_id.to_string(),
32 sign_name: sign_name.to_string(),
33 secret_id: secret_id.to_string(),
34 secret_key: secret_key.to_string(),
35 templated_data:templated_data.iter().map(|s| s.to_string()).collect(),
36 }
37 }
38 pub fn send(&mut self, authorization:&str)->Result<String, Error>{
39 let mut http = br_reqwest::Client::new();
40 let url= "https://sms.tencentcloudapi.com";
41 match http.post(url)
42 .header("Authorization", authorization)
43 .header("content-type", "application/json")
44 .header("X-TC-Action","SendSms")
45 .header("X-TC-Region","ap-guangzhou")
46 .header("X-TC-Timestamp",br_fields::datetime::Timestamp::timestamp().to_string().as_str())
47 .header("X-TC-Version","2021-01-11")
48 .header("Host","sms.tencentcloudapi.com")
49 .raw_json(object! {
50 "PhoneNumberSet": self.phone_number.clone(),
51 "SmsSdkAppId": self.sdk_appid.clone(),
52 "TemplateId": self.templated_id.clone(),
53 "SignName": self.sign_name.clone(),
54 "TemplateParamSet": self.templated_data.clone(),
55 })
56 .send().unwrap()
57 .json() {
58 Ok(e) => {
59 println!("发送成功{:#}",e);
60 }
61 Err(e) => {
62 println!("e{:?}",e);
63 }
64 };
65
66 Ok("".to_string())
67 }
68 pub fn sign(&mut self)->String{
70 let method = "POST";
72 let uri = "/";
73 let query_string = "";
74 let headers = "content-type:application/json\nhost:sms.tencentcloudapi.com\nx-tc-action:sendsms\n";
75 let signed_headers = "content-type;host;x-tc-action";
76 let payload = object!{
77 "PhoneNumberSet": self.phone_number.clone(),
78 "SmsSdkAppId": self.sdk_appid.clone(),
79 "TemplateId": self.templated_id.clone(),
80 "SignName": self.sign_name.clone(),
81 "TemplateParamSet": self.templated_data.clone(),
82 };
83
84 let payload = payload.to_string();
86 let canonical_request = build_canonical_request(method, uri, query_string, headers, signed_headers, payload.as_str());
87 let hashed_canonical_request = sha256_hex_lowercase(&canonical_request);
89 let service = "sms";
90 let binding = br_fields::datetime::Timestamp::timestamp().to_string();
91 let timestamp = binding.as_str();
92 let data = br_fields::datetime::Datetime::datetime_format("%Y-%m-%d").to_string();
93 let credential_scope = format!("{}/{}/tc3_request", data, service);
94 let algorithm = "TC3-HMAC-SHA256";
95
96 let string_to_sign = format!("{}\n{}\n{}\n{}", algorithm, timestamp, credential_scope, hashed_canonical_request);
98 let secret_date = hmac_sha256(format!("TC3{}", self.secret_key).as_bytes(), data.as_str());
100 let secret_service = hmac_sha256(&secret_date, service);
101 let secret_signing = hmac_sha256(&secret_service, "tc3_request");
102 let signature = hmac_sha256(&secret_signing, string_to_sign.as_str());
104 let hex_str: String = encode(signature);
105 let auth = build_authorization(self.secret_id.as_str(), credential_scope.as_str(), signed_headers, hex_str.as_str());
106 auth
107 }
108}
109fn build_canonical_request(
110 method: &str,
111 uri: &str,
112 query_string: &str,
113 headers: &str,
114 signed_headers: &str,
115 payload: &str,
116) -> String {
117 let hashed_payload = sha256_hex_lowercase(payload);
118 format!("{}\n{}\n{}\n{}\n{}\n{}", method, uri, query_string, headers, signed_headers, hashed_payload)
119}
120
121fn sha256_hex_lowercase(data: &str) -> String {
122 let hash = Sha256::digest(data.as_bytes());
123 format!("{:x}", hash)
124}
125type HmacSha256 = Hmac<Sha256>;
126fn hmac_sha256(key: &[u8], data: &str) -> Vec<u8> {
127 let mut mac = HmacSha256::new_from_slice(key).expect("HMAC can take key of any size");
128 mac.update(data.as_bytes());
129 mac.finalize().into_bytes().to_vec()
130}
131fn build_authorization(
132 secret_id: &str,
133 credential_scope: &str,
134 signed_headers: &str,
135 signature: &str,
136) -> String {
137 format!("TC3-HMAC-SHA256 Credential={}/{}, SignedHeaders={}, Signature={}", secret_id, credential_scope, signed_headers, signature
138 )
139}