login_wechat.h
#ifndef LOGIN_WECHAT_H
#define LOGIN_WECHAT_H
#include <QDialog>
#include <QLabel>
#include <QMap>
#include <QDebug>
#include <QTimer>
#include <QMessageBox>
#include <QDesktopServices>
#include <QUrl>
#include <QWebEngineView>
#include <QWebEngineSettings>
#include <QWebEngineUrlRequestInfo>
#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QTextCodec>
#include <QVariant>
#include <QCloseEvent>
typedef struct WechatAccessToken
{
QString _access_token; //access_token 网页授权接口调用凭证,注意:此access_token与基础支持的access_token不同
QString _expires_in; //expires_in access_token接口调用凭证超时时间,单位(秒)
QString _refresh_token; //refresh_token 用户刷新access_token
QString _openid; //openid 用户唯一标识,请注意,在未关注公众号时,用户访问公众号的网页,也会产生一个用户和公众号唯一的OpenID
QString _scope; //scope 用户授权的作用域,使用逗号(,)分隔
} WechatAccessToken ;
typedef struct{
QString _openid;
QString _nickname;
QString _sex;
QString _language;
QString _city;
QString _province;
QString _country;
QString _headimageurl;
QString _privilege;
QString _unionid;
} PersonalInfo ;
namespace Ui {
class Login_wechat;
}
class Login_wechat : public QDialog
{
Q_OBJECT
public:
explicit Login_wechat(QWidget *parent = 0);
~Login_wechat();
// void closeEvent(QCloseEvent *event);
QString sendARequest(QString myurl);
int loadTheWebPage(QString myUrl);
int getAccessToken(QString appId, QString appSecret, QString code);
int dealWithTokenString(QString message);
int getPersonalInfo(QString access_token, QString open_id);
int senAPost(QString senData);
int dealWithStatusString(QString statusMessage);
int dealWithPersonalStrings(QString personalString);
int downloadHeadImage(QString imageUrl);
int displayWaiting(QString username);
private slots:
void OnReplyFinshed(QNetworkReply* reply);
void OnLoadFinished();
void timeOutFunc();
void onUrlChanged(QUrl str);
private:
Ui::Login_wechat *ui;
QNetworkAccessManager *manager;
QWebEngineView *LiveView;
WechatAccessToken token;
PersonalInfo personalInfo;
QTimer *timer;
};
#endif // LOGIN_WECHAT_H
login_wechat.cpp
#include "login_wechat.h"
#include "ui_login_wechat.h"
#pragma execution_character_set("utf-8")
QString AppId = "wxfdf5***********7f";
QString AppSecret = "1a6fc***************bb46";
QString RedirectUrl = "http://baidu.com.cn";
static int personal_flag, status_flag, token_flag, clock_count;
QString token_message;
Login_wechat::Login_wechat(QWidget *parent) :
QDialog(parent),
ui(new Ui::Login_wechat)
{
ui->setupUi(this);
this->setWindowTitle("Login By Wechat");
LiveView = new QWebEngineView(this);
QString myurl = QString("https://open.weixin.qq.com/connect/qrconnect?appid=%1&redirect_uri=%2&response_type=code&state=idc_1qloO7huDcIYf9qpjYZ8WkA&scope=snsapi_login#wechat_redirect")
.arg(AppId).arg(RedirectUrl);
QString RequestUrl = sendARequest(myurl);
loadTheWebPage(RequestUrl);
timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(timeOutFunc()));
connect(manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(OnReplyFinshed(QNetworkReply*)));
connect(LiveView, SIGNAL(loadFinished(bool)), this, SLOT(OnLoadFinished()));
connect(LiveView, SIGNAL(urlChanged(QUrl)), this, SLOT(onUrlChanged(QUrl)));
}
Login_wechat::~Login_wechat()
{
delete ui;
}
QString Login_wechat::sendARequest(QString myurl)
{
qDebug() << "url = " << myurl;
manager = new QNetworkAccessManager();
manager->get(QNetworkRequest(QUrl(myurl)));
qDebug() << "Finished send a requset" << endl;
return myurl;
}
int Login_wechat::loadTheWebPage(QString myUrl)
{
LiveView->settings()->setAttribute(QWebEngineSettings::PluginsEnabled, true);
LiveView->setAttribute(Qt::WA_DeleteOnClose);
LiveView->load(QUrl(myUrl));
LiveView->resize(500, 500);
LiveView->show();
return 0;
}
int Login_wechat::getAccessToken(QString appId, QString appSecret, QString code)
{
QString toGetAccessToken = QString("https://api.weixin.qq.com/sns/oauth2/access_token?appid=%1&secret=%2&code=%3&grant_type=authorization_code")
.arg(appId).arg(appSecret).arg(code);
sendARequest(toGetAccessToken);
connect(manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(OnReplyFinshed(QNetworkReply*)));
return 0;
}
int Login_wechat::dealWithTokenString(QString message)
{
QMap<QString, QString> AccessTakenInfo;
message.replace("\"", "");
message.replace("{", "");
message.replace("}", "");
QStringList list = message.split(",");
QString info;
for(auto i = 0; i < list.size(); i++)
{
info = list.at(i);
AccessTakenInfo.insert(info.mid(0, info.indexOf(":")), info.mid(info.indexOf(":")+1));
}
token._access_token = AccessTakenInfo.find("access_token").value();
token._expires_in = AccessTakenInfo.find("expires_in").value();
token._refresh_token = AccessTakenInfo.find("refresh_token").value();
token._openid = AccessTakenInfo.find("openid").value();
token._scope = AccessTakenInfo.find("scope").value();
qDebug() << endl;
qDebug() << "token._access_token =" << token._access_token;
qDebug() << "token._expires_in =" << token._expires_in;
qDebug() << "token._refresh_token =" << token._refresh_token;
qDebug() << "token._openid =" << token._openid;
qDebug() << "token._scope =" << token._scope << endl;
getPersonalInfo(token._access_token, token._openid);
return 0;
}
int Login_wechat::getPersonalInfo(QString access_token, QString open_id)
{
QString url = QString("https://api.weixin.qq.com/sns/userinfo?access_token=%1&openid=%2").arg(access_token).arg(open_id);
QString str = sendARequest(url);
personal_flag = 9;
connect(manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(OnReplyFinshed(QNetworkReply*)));
return 0;
}
int Login_wechat::senAPost(QString senData)
{
QNetworkAccessManager *manager1 = new QNetworkAccessManager();
QNetworkRequest request;
QString postUrl = "";
request.setUrl(QUrl(postUrl));
request.setRawHeader("Content-Type","application/x-www-form-urlencoded");
manager1->post(request, senData.toUtf8().data());
connect(manager1, SIGNAL(finished(QNetworkReply*)), this, SLOT(OnReplyFinshed(QNetworkReply*)));
qDebug() << "sended a post" << endl;
delete manager1;
return 0;
}
int Login_wechat::dealWithStatusString(QString statusMessage)
{
qDebug() << "The status message need to deal with is that " << endl;
qDebug() << statusMessage << endl;
return 0;
}
int Login_wechat::dealWithPersonalStrings(QString personalString)
{
QMap<QString,QString> responeInfo;
personalString = personalString.replace("{", "");
personalString = personalString.replace("}", "");
personalString = personalString.replace("\\", "");
personalString = personalString.replace("\"", "");
QStringList list = personalString.split(",");
for(auto i = 0; i < list.size(); i++)
{
responeInfo.insert( QString(list.at(i)).mid(0,QString(list.at(i)).indexOf(":")), QString(list.at(i)).mid(QString(list.at(i)).indexOf(":")+1) );
}
personalInfo._openid = responeInfo.find("openid").value();
personalInfo._nickname = responeInfo.find("nickname").value();
personalInfo._headimageurl = responeInfo.find("headimgurl").value();
personalInfo._city = responeInfo.find("city").value();
personalInfo._country = responeInfo.find("country").value();
personalInfo._language = responeInfo.find("language").value();
personalInfo._privilege = responeInfo.find("privilege").value();
personalInfo._province = responeInfo.find("province").value();
personalInfo._sex = responeInfo.find("sex").value();
personalInfo._unionid = responeInfo.find("unionid").value();
return 0;
}
int Login_wechat::downloadHeadImage(QString imageUrl)
{
qDebug() << "downloading..." << endl;
//构造请求
QNetworkAccessManager manager;
QNetworkRequest request;
request.setUrl(imageUrl);
// 发送请求
QNetworkReply *reply = manager.get(request);
//开启一个局部的事件循环,等待响应结束,退出
QEventLoop loop;
QObject::connect(reply, SIGNAL(finished()), &loop, SLOT(quit()));
loop.exec();
//判断是否出错,出错则结束
if (reply->error() != QNetworkReply::NoError)
{
return -1;
}
//保存文件
QFile file("headImage.jpg");
if(!file.open(QIODevice::WriteOnly))
return -1;
file.write(reply->readAll());
file.close();
delete reply;
return 0;
}
int Login_wechat::displayWaiting(QString username)
{
ui->nickname->setText(personalInfo._nickname);
ui->label->setStyleSheet(QString("{border:1px solid black;border-radius:5px;}"));
QImage img;
img.load("headImage.jpg");
ui->label->setPixmap(QPixmap::fromImage(img));
return 0;
}
void Login_wechat::OnReplyFinshed(QNetworkReply *reply)
{
QVariant variant = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute);
int status = variant.toInt();
qDebug() << "status = " << status;
QTextCodec *codec = QTextCodec::codecForName("utf8"); //使用utf8编码,这样才可以显示中文
QString all = codec->toUnicode(reply->readAll());
// 已经发送了 post 请求,在此获取返回的状态码
if(status_flag == 9)
{
// TODO
// 获取整个返回数据
}
// 已经发送了获取 access_token 数据请求,在此接受返回数据
if(token_flag == 9)
{
dealWithTokenString(all);
}
// 已经发送了个人信息数据请求,在此接受返回数据
if(personal_flag == 9)
{
if(all.indexOf("nickname") != -1)
{
// Send it json data to the back end
qDebug() << all << endl;
dealWithPersonalStrings(all);
downloadHeadImage(personalInfo._headimageurl);
displayWaiting(personalInfo._nickname);
senAPost(all);
status_flag = 9;
personal_flag = 0;
}
}
// 接收完 access_token 数据,将浏览器窗口关闭
if(token_flag == 9)
{
qDebug() << "\nClose the view 277" << endl;
LiveView->close();
token_flag = 0;
}
reply->deleteLater(); //最后要释放reply对象
}
void Login_wechat::OnLoadFinished()
{
QString currentUrl = LiveView->url().toString();
if(currentUrl.indexOf("code=") != -1)
{
QString code = currentUrl.mid( currentUrl.indexOf("code=")+5, (currentUrl.indexOf("&s")-currentUrl.indexOf("code=")-5) );
QString state = currentUrl.mid( currentUrl.indexOf("state=")+6 );
connect(LiveView, SIGNAL(loadFinished(bool)), this, SLOT(OnLoadFinished()));
token_flag = 9;
getAccessToken(AppId, AppSecret, code);
}
}
void Login_wechat::timeOutFunc()
{
clock_count++;
if(clock_count % 3 == 0)
{
ui->tips->setText("登陆中,请稍后...");
}
else if(clock_count % 3 == 1)
{
ui->tips->setText("登陆中,请稍后.");
}
else if(clock_count % 3 == 2)
{
ui->tips->setText("登陆中,请稍后..");
}
}
void Login_wechat::onUrlChanged(QUrl str)
{
if(str.toString().indexOf("code=") != -1)
{
timer->start(500);
this->show();
LiveView->hide();
}
}