QT 微信第三方授权登录

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();
    }
}

  • 1
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
### 回答1: Qt酷炫第三方控件是指基于Qt框架开发的一系列具有炫酷效果和丰富功能的控件。这些第三方控件可以用于Qt应用程序的界面设计和功能增强。 Qt酷炫第三方控件的下载可以通过以下几种方式进行: 1. 官方网站下载:一些第三方控件的开发者会将其作品发布在Qt官方网站上,用户可以直接在官网上找到需要的控件,并进行下载。在官网上下载的控件通常是经过验证和测试的,稳定性较高。 2. 第三方开源软件库:有些开源的软件库专门收集和整理了大量的Qt酷炫第三方控件,并提供给用户下载使用。用户可以在这些软件库中搜索需要的控件,并通过链接进行下载。 3. 社区论坛或博客:很多Qt爱好者和开发者会将自己开发的炫酷控件分享到社区论坛或个人博客中。用户可以在这些平台上搜索相关资源,找到心仪的控件,并进行下载。 无论是通过官方网站下载、第三方开源软件库还是社区论坛或博客下载,用户在下载Qt酷炫第三方控件时需要注意以下几点: 1. 控件的版本兼容性:确保所下载的控件与自己的Qt框架版本兼容,否则可能导致控件无法正常运行或出现bug。 2. 授权问题:有些Qt酷炫第三方控件可能需要付费使用或遵守特殊的授权协议,用户在下载和使用控件前,应该了解其授权方式,并遵守相关规定。 总之,Qt酷炫第三方控件的下载可以通过官方网站、第三方开源软件库或社区论坛博客等途径进行。在下载过程中,用户应注意控件的版本兼容性和授权问题,以确保能够顺利使用这些炫酷的控件。 ### 回答2: Qt是一款跨平台的应用程序开发框架,其提供了丰富的控件和功能,使得开发者能够快速开发各种类型的应用程序。Qt提供了众多的第三方控件,使得开发者可以更加方便地实现各种炫酷的界面效果。 首先,Qt提供了一系列的控件库,如Qt Widgets、Qt Quick和Qt Quick Controls等,其中包含了丰富多样的控件,如按钮、标签、文本框、进度条等,开发者可以根据自己的需求选择合适的控件进行使用。 此外,Qt还提供了一些炫酷的第三方控件,如QtitanRibbon和QtitanDocking等,它们基于Qt进行开发,具有各种炫酷的界面效果和交互效果。比如,QtitanRibbon是一个强大的Ribbon控件,可以实现类似于Office软件中的功能区效果;而QtitanDocking是一个可拖拽的停靠式窗口控件,可以实现类似Visual Studio中的界面效果。 对于开发者而言,使用这些炫酷的第三方控件可以大大提升开发效率和用户体验。通过独特的界面效果和交互方式,可以使应用程序更加吸引人,并提供更好的用户体验。同时,这些第三方控件还提供了丰富的配置选项,使得开发者可以按照自己的需求进行定制。 总之,Qt提供了众多的第三方控件,可以帮助开发者实现各种炫酷的界面效果。这些控件不仅提供了丰富的功能,同时还具有可定制性和跨平台性等优势,使得开发者能够更加便捷地创建出令人印象深刻的应用程序。 ### 回答3: QT 是一种跨平台的开发框架,可以用于开发各种类型的应用程序。QT 提供了大量的内置控件,但有时我们需要更酷炫的第三方控件来增强应用的功能和界面效果。 在 QT 中,我们可以通过多种途径下载和使用酷炫的第三方控件。其中一种途径是通过 QT 官方网站的插件市场,这里有很多开发者上传和分享了自己开发的第三方控件。我们可以在插件市场中搜索到我们需要的控件,然后下载并引入到自己的项目中进行使用。 另一种途径是通过 GitHub 这样的代码托管平台,许多开发者把自己开发的控件代码放在了 GitHub 上供其他开发者使用。我们可以通过搜索引擎找到我们需要的控件项目,然后在项目页面中找到控件的源代码和下载方式。 在下载第三方控件之前,我们需要确保控件的兼容性和稳定性。我们可以查看控件的说明文档、开发者的推荐使用版本和用户的评价来判断控件的质量。另外,我们也可以查看控件的最新更新时间和开发者的活跃度,这可以帮助我们判断该控件是否具有良好的维护和持续改进。 总之,通过 QT 官方网站的插件市场和 GitHub 这样的代码托管平台,我们可以方便地下载和使用酷炫的第三方控件,来增强我们的应用程序的功能和界面效果。
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值