admin 管理员组文章数量: 886992
QT POST方法:以使用腾讯云发送短信为例
- 1、准备
- 2、随机数
- 3、时间戳
- 4、哈希算法
- 5、签名方法
- 6、POST结合使用
POST方法是制作软件中常用的一个方法,而验证码短信在各种注册操作中需要用到,所以本文将这两个结合起来写。文章还涉及到QT随机数的生成、时间戳、哈希算法等。
1、准备
因为用到了腾讯云,所以需要按腾讯云的要求做些准备,认证什么的需要自己搞定,然后发送短信相关的签名和模板也不是很困难。https://cloud.tencent/document/product/382/37745,帮助文档里有介绍,按里面的要求来就可以了。
腾讯云提供了API Explorer进行代码的调试https://console.cloud.tencent/api/explorer?Product=sms&Version=2019-07-11&Action=SendSms&SignVersion=,这个调试工具还是很好用的。
在代码写之前,需要先看一下需要请求的参数,这个帮助文档写的头大,他把公共参数与签名操作写在了一起,请求参数在另一部分,所以需要研究一番。这个时候腾讯提供的API Explorer起作用了,这个东东把需要的参数放一起了。。。。腾讯这里有两个签名方法,他推荐使用v3,我用的是v1,诸位注意一下。
我这里列出来了:
{
'Action' : 'SendSms',//固定
'Language' : 'zh-CN',//固定
'Nonce' : '',//随机数,我这里用了4位正整数
'PhoneNumberSet.0' : '',//手机号,如果有多个手机号,从0开始数
'Region' : '',//区域,空
'SecretId' : '',//这个填自己的,腾讯有写怎么获取
'SmsSdkAppid' : '',//这个填自己的,腾讯有写怎么获取
'TemplateID' : '',//这个填自己的,腾讯有写怎么获取
'TemplateParamSet.0' : '',//模板参数
'TemplateParamSet.1' : '',//模板参数
'Timestamp' : '',//时间戳
'Version' : '2019-07-11',//版本,固定
}
我这里使用的模板是这样的:
您正在申请手机注册,验证码为:{1},{2}分钟内有效!
{1}{2},就是模板参数,申请模板的时候从1开始,代码编写从0开始。
2、随机数
QT在5.10版本之后增加了一个函数用于产生随机数,qrand()和rand()不再推荐使用。
#include <QRandomGenerator>
QString randomNumber;
void MainWindow::generateRandomNumber()
{
randomNumber = "";
for (int i = 0; i < 4; i++)
{
randomNumber = randomNumber + QString("%1").arg(QRandomGenerator::global()->bounded(10));//不再使用qrand和qsrand
}
qDebug()<<randomNumber;
}
3、时间戳
时间戳也很常用,也很简单,腾讯写里使用时间戳,如果请求发送的时间,与标记的时间相差太长,会返回错误。
#include <QDateTime>
int Timestamp = QDateTime::currentDateTime().toTime_t();//时间戳
/// QT6.0中有更新,用下面这个方法
int Timestamp = QDateTime::currentSecsSinceEpoch();//这个返回的是秒数
4、哈希算法
公共参数里面有个Signature,这个是腾讯需要的一个签名,需要用到加密算法。**使用签名方法 v1 (有时会称作 HmacSHA256 和 HmacSHA1),公共参数需要统一放到请求串中。**初学者知道怎么用就行了。https://blog.csdn/WMX843230304WMX/article/details/73649294
#include <QCryptographicHash>//哈希算法
QByteArray arrayFromHexString;//计算哈希算法
private slots:
void slot_GetHash_Base64(QByteArray, QByteArray);//哈希算法Base64输出
void MainWindow::slot_GetHash_Base64(QByteArray key, QByteArray baseString)//计算哈希算法,以Base64输出
{
/*!
* \brief Qt hmacSha1 哈希算法
* \param key 加密需要的key
* \param baseString 需要加密的字符串
* \return QByteArray 加密后的数据内存中的ASCII码
*/
arrayFromHexString = "";
int blockSize = 64; // HMAC-SHA-1 block size, defined in SHA-1 standard
if (key.length() > blockSize) { // if key is longer than block size (64), reduce key length with SHA-1 compression
key = QCryptographicHash::hash(key, QCryptographicHash::Sha1);
}
QByteArray innerPadding(blockSize, char(0x36)); // initialize inner padding with char "6"
QByteArray outerPadding(blockSize, char(0x5c)); // initialize outer padding with char "/"
// ascii characters 0x36 ("6") and 0x5c ("/") are selected because they have large
// Hamming distance (http://en.wikipedia/wiki/Hamming_distance)
for (int i = 0; i < key.length(); i++) {
innerPadding[i] = innerPadding[i] ^ key.at(i); // XOR operation between every byte in key and innerpadding, of key length
outerPadding[i] = outerPadding[i] ^ key.at(i); // XOR operation between every byte in key and outerpadding, of key length
}
// result = hash ( outerPadding CONCAT hash ( innerPadding CONCAT baseString ) ).toBase64
QByteArray total = outerPadding;
QByteArray part = innerPadding;
part.append(baseString);
total.append(QCryptographicHash::hash(part, QCryptographicHash::Sha1));
QByteArray hashed = QCryptographicHash::hash(total, QCryptographicHash::Sha1);
/// https://1024tools/hmac
/// 这一网址提供两个参考,结果A:QByteArray::fromHex(hashed.toHex()).toHex();
/// 把结果A以Base64输出即下面的结果
/// 注意——>把字符串hashed转换为Hex,内存中的ASCII码arrayFromHexString
/// arrayFromHexString = QByteArray::fromHex(hashed.toHex()).toHex().toBase64()
/// 结果B:返回原始二进制进行Base64输出:
arrayFromHexString = QByteArray::fromHex(hashed.toHex()).toBase64().toPercentEncoding();//转换成Base64之后进行URL编码
//qDebug()<<"hmacSha1内存中的ASCII码 arrayFromHexString \n"<<arrayFromHexString;
}
这里需要注意的是最后的注释,腾讯所需要的是下图中的结果B,上面代码块所来源的链接中的输出结果是对A进行编码,区别就在一个toHex()。
5、签名方法
整个过程中比较困难的是这个签名方法,还是推荐使用API Explorer进行调试。签名实现的过程很简单,但是需要细心调试。
1、参数排序
2、拼接请求字符串
3、拼接签名原文字符串
4、加密签名串
5、签名串编码
1、2、3比较简单,需要耐心,这里列出4、5的操作。
this->generateRandomNumber();
//定义输入参数
QString Action = "SendSms";
QString Nonce = randomNumber;//随机正整数
QString PhoneNumberSet = "86"+ui->lineEdit_reg_tel->text();//这里很坑爹,文档里要求带“+86”,实际上腾讯自己把“+”带上了,所以只加“86”就行了
QString SecretId = "**************";
QString SmsSdkAppid = "*********";
QString TemplateID = "********";
Timestamp = QDateTime::currentDateTime().toTime_t();//时间戳
QString Version = "2019-07-11";
//拼接字符串
QString str = QString("POSTsms.tencentcloudapi/?Action=%1&Language=zh-CN&Nonce=%2&PhoneNumberSet.0=%3&Region=&SecretId=%4&SmsSdkAppid=%5&TemplateID=%6&TemplateParamSet.0=%7&TemplateParamSet.1=5&Timestamp=%8&Version=%9")
.arg(Action).arg(Nonce).arg(PhoneNumberSet).arg(SecretId).arg(SmsSdkAppid).arg(TemplateID).arg(Nonce).arg(Timestamp).arg(Version);
//qDebug()<<"str = : "<<str;
//计算哈希字符串,以Base64输出,进行url编码
QString SecretKey = "*************";
this->slot_GetHash_Base64(SecretKey.toUtf8(), str.toUtf8());//这个toUtf8()
QString Signature(arrayFromHexString);
qDebug()<<"签名:\n"<<Signature;
这里输出的签名和API Explorer中的对照,一样就OK了。
6、POST结合使用
到这里就可以使用POST方法了,也很简单,这里只列出请求的方法,返回结果是JSON格式,诸位思考一下吧。
//开始请求
QUrl url = QUrl(QString("https://sms.tencentcloudapi/"));
QString PostData = QString("Action=%1&Language=%2&Nonce=%3&PhoneNumberSet.0=%4&Region=%5&SecretId=%6&SmsSdkAppid=%7&TemplateID=%8&Timestamp=%9&Version=%10&TemplateParamSet.0=%11&TemplateParamSet.1=5&Signature=%12")
.arg(Action).arg("zh-CN").arg(Nonce).arg(PhoneNumberSet).arg("").arg(SecretId).arg(SmsSdkAppid).arg(TemplateID).arg(Timestamp).arg(Version).arg(Nonce).arg(Signature);
/// 这里需要注意一下,把Signature放最后,签名串加密完之后的字符最后一般是个“=”,编码之后变成了“%3D”这样,但是这个“=”还是会影响PostData的拼接,所以把Signature放最后,诸位可以按排序进行拼接试试,腾讯会报错。
qDebug()<<"postdata:\n"<<PostData;
QNetworkAccessManager *manager = new QNetworkAccessManager(this);
connect(manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(slot_requestFinished_SMS(QNetworkReply*)));
QNetworkRequest request;
request.setUrl(url);
request.setRawHeader("Content-Type", "application/x-www-form-urlencoded");
manager->post(request, PostData.toUtf8());
PS:
有一些平台,不涉及金融、Money等的过程,对签名的要求比较简单,可以采用比如Md5算法等,
QString txt = content + secretKey;
QByteArray base64 = QCryptographicHash::hash(txt.toLatin1(), QCryptographicHash::Md5).toBase64();
QString data_digest(base64);
这样几行代码就可以实现加签,签名有时个会带“+”号,一些平台会提示验签不通过,此时多加一步urlencode:
QString ddata_digest = QUrl::toPercentEncoding(data_digest);
这样字符串里面的“+”"="这些就会被替换掉。
版权声明:本文标题:QT POST方法:以使用腾讯云发送短信为例 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.freenas.com.cn/jishu/1734008141h1653990.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论