修改手机号码
前言
在上一集我们完成了获取验证码的功能,那么我们就可以完成我们的修改手机号码的功能了。
需求分析
我们获取完验证码之后,输入我们获取的验证码,之后修改我们的电话,如:1314520
我们的个人信息窗口就会改变我们的手机号码。
而且我们修改成功之后我们再次点击修改,我们的获取验证码的按钮不应该还在倒计时,应该进行重置,而且我们的验证码输入框也应该清空!
这就是我们的需求,那么我们来看一下我们的URL和请求响应的定义。
这就是我们修改绑定手机的http的URL
这就是我们http的请求和响应的定义。
那么就开始这一集的任务的代码编写吧。
客户端
我们还是需要先对提交按钮进行信号槽的连接,当我们点击修改手机号码提交按钮,我们就会触发一个函数,用于处理相关的逻辑。
connect(phoneSubmitBtn, &QPushButton::clicked, this, &SelfInfoWidget::clickPhoneSubmitBtn);
我们触发了这个函数,这个函数必须先判定我们是否获取到了验证码,我们要去DataCenter中获取验证码id,如果这个验证码没有收到就提示一下用户。如果我们收到了验证码,就可以重置我们的验证码id了,当然我们的验证码也不能是空的!之后发送请求前,我们需要将验证码输入框的内容清空。发送完请求之后,我们还可以重置一下我们的获取验证码的时间。
void SelfInfoWidget::clickPhoneSubmitBtn()
{
//先判定验证码是否收到
DataCenter* dataCenter = DataCenter::getInstance();
QString verifyCodeId = dataCenter->getVerifyCodeId();
if(verifyCodeId.isEmpty()){
//服务器还没返回验证码响应
Toast::showMessage("服务器尚未返回验证码!稍后重试!");
return;
}
//如果当前已经拿到verifyCodeId,就可以清空DataCenter存储的值,确保下次点击提交按钮,逻辑依旧生效
dataCenter->resetVerifyCodeId("");
//获取用户输入的验证码
const QString verifyCode = verifyCodeEdit->text();
if(verifyCode.isEmpty()){
Toast::showMessage("验证码不能为空");
}
//清空验证码输入框内容
verifyCodeEdit->setText("");
//发送请求,把当前验证码信息发送到服务器
connect(dataCenter, &DataCenter::changePhoneDone, this, &SelfInfoWidget::clickPhoneSubmitBtnDone, Qt::UniqueConnection);
dataCenter->changePhoneAsync(this->phoneToChange, verifyCodeId, verifyCode);
//验证码按钮的倒计时停止
leftTime = 1;
}
之后就要通过DataCenter传递所需参数到网络通信那边,我们这次就需要传递loginSessionId了。
void DataCenter::changePhoneAsync(const QString &phone, const QString &verifyCodeId, const QString &verifyCode)
{
netClient.changePhone(loginSessionId, phone, verifyCodeId, verifyCode);
}
一次修改手机号,我们还要传递手机号,验证码id以及验证码。
之后到了网络通信这边还是正常的几部曲,构造http请求,发送请求,处理http响应。
void NetClient::changePhone(const QString &loginSessionId, const QString &phone, const QString &verifyCodeId, const QString &verifyCode)
{
//构造http请求body
bite_im::SetUserPhoneNumberReq pbReq;
pbReq.setRequestId(makeRequestId());
pbReq.setSessionId(loginSessionId);
pbReq.setPhoneNumber(phone);
pbReq.setPhoneVerifyCodeId(verifyCodeId);
pbReq.setPhoneVerifyCode(verifyCode);
QByteArray body = pbReq.serialize(&serializer);
LOG() << "[修改手机号] 发送请求 requestId=" << pbReq.requestId() << ", phone=" << phone << ", loginSessionId=" << pbReq.sessionId()
<< ", verifyCodeId=" << pbReq.phoneVerifyCodeId() <<", verifyCode=" << pbReq.phoneVerifyCode();
//发送http请求
QNetworkReply* resp = this->sendHttpRequest("/service/user/set_phone", body);
//处理响应
connect(resp, &QNetworkReply::finished, this, [=](){
bool ok = false;
QString reason;
auto pbResp = this->handleHttpResponse<bite_im::SetUserPhoneNumberRsp>(resp, &ok, &reason);
//判定是否出错
if(!ok){
LOG() << "[修改手机号]失败!reason=" << reason;
return;
}
//设置数据到DataCenter
dataCenter->resetPhone(phone);
//发送信号,通知调用
emit dataCenter->changePhoneDone();
LOG() << "[修改手机号] 处理响应完毕! requestId=" << pbResp->requestId();
});
}
我们响应回来之后,如果没有出错,就要重置一下我们DataCenter中myself变量里的phone属性。并且发送一个信号,告诉调用者我们的http响应处理完毕。
也就是回到这个信号槽
connect(dataCenter, &DataCenter::changePhoneDone, this, &SelfInfoWidget::clickPhoneSubmitBtnDone, Qt::UniqueConnection);
这里我们就会修改我们的UI界面,并且将我们修改的手机号码显示到我们的界面上。
void SelfInfoWidget::clickPhoneSubmitBtnDone()
{
layout->removeWidget(verifyCodeTag);
layout->removeWidget(verifyCodeEdit);
layout->removeWidget(getVerifyCodeBtn);
layout->removeWidget(phoneEdit);
layout->removeWidget(phoneSubmitBtn);
verifyCodeTag->hide();
verifyCodeEdit->hide();
getVerifyCodeBtn->hide();
phoneEdit->hide();
phoneSubmitBtn->hide();
layout->addWidget(phoneLabel,3,2);
layout->addWidget(phoneModifyBtn,3,3);
phoneLabel->show();
phoneLabel->setText(this->phoneToChange);
phoneModifyBtn->show();
}
这就是客户端这边的内容。
测试服务器
也是两个步骤,第一步就是按照proto文件定义的URL配置请求的路由。
httpServer.route("/service/user/set_phone", [=](const QHttpServerRequest& req){
return this->setPhone(req);
});
第二步,根据proto文件定义的响应样式进行构造响应。
QHttpServerResponse HttpServer::setPhone(const QHttpServerRequest &req)
{
//解析请求
bite_im::SetUserPhoneNumberReq pbReq;
pbReq.deserialize(&serializer, req.body());
LOG() << "[REQ 修改手机号] requestId=" << pbReq.requestId() << ", loginSessionId=" << pbReq.sessionId() << ", phone=" << pbReq.phoneNumber()
<<", verifyCodeId=" << pbReq.phoneVerifyCodeId() << ", verifyCode=" << pbReq.phoneVerifyCode();
//构造响应
bite_im::SetUserPhoneNumberRsp pbResp;
pbResp.setRequestId(pbReq.requestId());
pbResp.setSuccess(true);
pbResp.setErrmsg("");
QByteArray body = pbResp.serialize(&serializer);
//构造http响应
QHttpServerResponse resp(body, QHttpServerResponse::StatusCode::Ok);
resp.setHeader("Content-Type", "application/x-protobuf");
return resp;
}
测试服务器这边就完成了。
那么我们的功能也就实现了,那么这一集就到这里。