Implemented response parsing.

master
Josef Rokos 8 years ago
parent 90c8110bd2
commit 1c4976cb0b

@ -11,13 +11,18 @@ int main(int argc, char *argv[])
request.setCelkTrzba(1);
request.setCerpZuct(2);
request.setCestSluz(3);
request.setDatOdesl(QDateTime::currentDateTime());
request.setPrvniZaslani(true);
request.setIdPokl("id pokladny");
request.setIdProvoz("id provoz");
request.setDicPopl("CZ1234567");
request.setIdProvoz("1");
request.setDicPopl("CZ1212121218");
request.setPoradCis("123/5");
request.setDatTrzby(QDateTime::currentDateTime());
request.setCelkTrzba(100);
request.setRezim(EetRequest::STANDARD);
EetSender sender;
sender.setupSigner("/home/pepa/Dokumenty/dev/eet/01000003.p12", "eet");
sender.setupSigner("/home/pepa/Dokumenty/dev/eet/121212.p12", "eet");
sender.sendRequest(&request);
return a.exec();

@ -3,8 +3,6 @@
EetRequest::EetRequest(QObject *parent) : QObject(parent)
{
m_prvniZaslani = true;
m_produkcni = false;
m_rezim = STANDARD;
}
@ -67,19 +65,20 @@ QString EetRequest::uuidZpravyStr() const
return ret;
}
bool EetRequest::produkcni() const
bool EetRequest::overeni() const
{
return m_produkcni;
return m_overeni.isNull() ? false : *m_overeni.data();
}
void EetRequest::setProdukcni(bool produkcni)
void EetRequest::setOvereni(bool overeni)
{
m_produkcni = produkcni;
m_overeni = QSharedPointer<bool>(new bool);
*m_overeni.data() = overeni;
}
QString EetRequest::produkcniStr() const
QString EetRequest::overeniStr() const
{
return m_produkcni ? "true" : "false";
return m_overeni.isNull() ? NULL_VAL : (*m_overeni.data() ? "true" : "false");
}
QString EetRequest::dicPopl() const

@ -17,7 +17,7 @@ class EETCPPSHARED_EXPORT EetRequest : public QObject
Q_PROPERTY(QString dat_odesl READ datOdeslStr)
Q_PROPERTY(QString prvni_zaslani READ prvniZaslaniStr)
Q_PROPERTY(QString uuid_zpravy READ uuidZpravyStr)
Q_PROPERTY(QString produkcni READ produkcniStr)
Q_PROPERTY(QString overeni READ overeniStr)
Q_PROPERTY(QString dic_popl READ dicPopl)
Q_PROPERTY(QString dic_poverujiciho READ dicPoverujiciho)
Q_PROPERTY(QString id_provoz READ idProvoz)
@ -63,9 +63,9 @@ public:
void setUuidZpravy(const QUuid &uuidZpravy);
QString uuidZpravyStr() const;
bool produkcni() const;
void setProdukcni(bool produkcni);
QString produkcniStr() const;
bool overeni() const;
void setOvereni(bool overeni);
QString overeniStr() const;
QString dicPopl() const;
void setDicPopl(const QString &dicPopl);
@ -154,7 +154,7 @@ private:
QTimeZone m_datOdeslZone;
bool m_prvniZaslani;
QUuid m_uuidZpravy;
bool m_produkcni;
QSharedPointer<bool> m_overeni;
QSharedPointer<QString> m_dicPopl;
QSharedPointer<QString> m_dicPoverujiciho;
QString m_idProvoz;

@ -0,0 +1,99 @@
#include "eetresult.h"
EetResult::EetResult(QObject *parent) : QObject(parent)
{
m_status = RESPONSE_OK;
}
EetResult::ResponseStatus EetResult::status() const
{
return m_status;
}
void EetResult::setStatus(const EetResult::ResponseStatus &status)
{
m_status = status;
}
QString EetResult::fik() const
{
return m_fik;
}
void EetResult::setFik(const QString &fik)
{
m_fik = fik;
}
EetMessageList EetResult::warnings() const
{
return m_warnings;
}
void EetResult::setWarnings(const EetMessageList &warnings)
{
m_warnings = warnings;
}
EetMessageList EetResult::errors() const
{
return m_errors;
}
void EetResult::setErrors(const EetMessageList &errors)
{
m_errors = errors;
}
QUuid EetResult::uuid() const
{
return m_uuid;
}
void EetResult::setUuid(const QUuid &uuid)
{
m_uuid = uuid;
}
QDateTime EetResult::reciveDate() const
{
return m_reciveDate;
}
void EetResult::setReciveDate(const QDateTime &reciveDate)
{
m_reciveDate = reciveDate;
}
EetMessage::EetMessage(QObject *parent)
:QObject(parent)
{
m_code = 0;
}
EetMessage::EetMessage(int code, const QString &message, QObject *parent)
:QObject(parent)
{
m_code = code;
m_message = message;
}
int EetMessage::code() const
{
return m_code;
}
void EetMessage::setCode(int code)
{
m_code = code;
}
QString EetMessage::message() const
{
return m_message;
}
void EetMessage::setMessage(const QString &message)
{
m_message = message;
}

@ -0,0 +1,72 @@
#ifndef EETRESULT_H
#define EETRESULT_H
#include <QObject>
#include <QUuid>
#include <QString>
#include <QList>
#include <QDateTime>
class EetMessage : public QObject
{
Q_OBJECT
public:
explicit EetMessage(QObject *parent = 0);
EetMessage(int code, const QString &message, QObject *parent = 0);
int code() const;
void setCode(int code);
QString message() const;
void setMessage(const QString &message);
private:
int m_code;
QString m_message;
};
typedef QList<EetMessage*> EetMessageList;
class EetResult : public QObject
{
Q_OBJECT
public:
enum ResponseStatus
{
RESPONSE_OK = 0,
DATA_ERROR,
SERVER_ERROR,
SSL_ERROR,
TIMEDOUT
};
explicit EetResult(QObject *parent = 0);
ResponseStatus status() const;
void setStatus(const ResponseStatus &status);
QString fik() const;
void setFik(const QString &fik);
EetMessageList warnings() const;
void setWarnings(const EetMessageList &warnings);
EetMessageList errors() const;
void setErrors(const EetMessageList &errors);
QUuid uuid() const;
void setUuid(const QUuid &uuid);
QDateTime reciveDate() const;
void setReciveDate(const QDateTime &reciveDate);
private:
ResponseStatus m_status;
QUuid m_uuid;
QDateTime m_reciveDate;
QString m_fik;
EetMessageList m_warnings;
EetMessageList m_errors;
};
#endif // EETRESULT_H

@ -1,11 +1,35 @@
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include "eetsender.h"
#include "eetsigner.h"
#include <QDebug>
#include <QFile>
#include <QDomNode>
#include <QDomDocument>
#include <QXmlQuery>
#include <QXmlResultItems>
#include <QNetworkConfiguration>
const QString EetSender::ms_nsDef = "declare namespace eet = \"http://fs.mfcr.cz/eet/schema/v3\";\n"
"declare namespace ds = \"http://www.w3.org/2000/09/xmldsig#\";\n"
"declare namespace wsu = \"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\";\n"
"declare namespace wsse = \"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd\";\n"
"declare namespace senc = \"http://schemas.xmlsoap.org/soap/encoding/\";\n"
"declare namespace senv = \"http://schemas.xmlsoap.org/soap/envelope/\";\n";
EetSender::EetSender(QObject *parent) : QObject(parent)
{
m_signer = nullptr;
m_resut = nullptr;
m_checkSignature = true;
m_manager = new QNetworkAccessManager(this);
connect(m_manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(replyFinished(QNetworkReply*)));
connect(m_manager, &QNetworkAccessManager::sslErrors, [this](QNetworkReply *rep, QList<QSslError> errs){
emit serviceCertError();
});
}
void EetSender::sendRequest(EetRequest *request)
@ -36,7 +60,12 @@ void EetSender::sendRequest(EetRequest *request)
QString strRequest = tempRequest.fillTemplate(val);
qDebug() << strRequest;
QNetworkRequest req(QUrl("https://pg.eet.cz/eet/services/EETServiceSOAP/v3"));
m_manager->post(req, strRequest.toUtf8());
QFile file("/home/pepa/Dokumenty/dev/eet/req.xml");
file.open(QIODevice::WriteOnly);
file.write(strRequest.toUtf8());
}
void EetSender::setupSigner(const QString &certPath, const QString &passwd)
@ -49,3 +78,191 @@ void EetSender::setupSigner(const QString &certPath, const QString &passwd)
m_signer = new EetSigner(this);
m_signer->setup(certPath, QCA::SecureArray(passwd.toUtf8()));
}
void EetSender::setCheckSignature(bool checkSignature)
{
m_checkSignature = checkSignature;
}
bool EetSender::checkSignature() const
{
return m_checkSignature;
}
EetResult *EetSender::resut() const
{
return m_resut;
}
bool EetSender::verifySignature(const QByteArray &repData)
{
QString queryString("//senv:Envelope/senv:Header/wsse:Security/ds:Signature/ds:SignedInfo");
QString signedInfo, certB64, signatureB64;
QXmlQuery q;
q.setFocus(QString(repData));
q.setQuery(ms_nsDef + queryString);
q.evaluateTo(&signedInfo);
QStringList list = signedInfo.split("\n");
signedInfo = "<SignedInfo xmlns=\"http://www.w3.org/2000/09/xmldsig#\">\n";
for (int i = 1; i < list.length(); i++)
{
QString line = list[i];
line = line.replace(QRegExp("^(\\s+)<([A-Za-z]+)([A-Za-z0-9-\"=/#:\\.\\ ]+)/>"), "\\1<\\2\\3></\\2>");
signedInfo += line + "\n";
}
signedInfo = signedInfo.trimmed();
signedInfo = signedInfo.replace(" ", " ");
queryString = "//senv:Envelope/senv:Header/wsse:Security/wsse:BinarySecurityToken/text()";
q.setQuery(ms_nsDef + queryString);
q.evaluateTo(&certB64);
queryString = "//senv:Envelope/senv:Header/wsse:Security/ds:Signature/ds:SignatureValue/text()";
q.setQuery(ms_nsDef + queryString);
q.evaluateTo(&signatureB64);
QCA::ConvertResult res;
QCA::Certificate cert = QCA::Certificate::fromDER(QByteArray::fromBase64(certB64.toUtf8()), &res);
if (res != QCA::ConvertGood)
{
emit serviceCertError();
return false;
}
QCA::PublicKey pubKey = cert.subjectPublicKey();
if (!pubKey.canVerify())
{
emit serviceCertError();
return false;
}
bool signValid = pubKey.verifyMessage(QCA::MemoryRegion(signedInfo.toUtf8()), QByteArray::fromBase64(signatureB64.toUtf8()), QCA::EMSA3_SHA256);
if (!signValid)
{
emit signInvalid();
return false;
}
return true;
}
void EetSender::replyFinished(QNetworkReply *reply)
{
if (reply->error() != QNetworkReply::NoError)
{
emit sendError();
reply->deleteLater();
return;
}
QByteArray repData = reply->readAll();
/*QFile file("/home/pepa/Dokumenty/dev/eet/reply.xml");
file.open(QIODevice::ReadOnly);
repData = file.readAll();*/
if (m_checkSignature && !verifySignature(repData))
{
return;
}
QXmlQuery q;
q.setFocus(QString(repData));
QString result;
QString queryString("//senv:Envelope/senv:Body/eet:Odpoved/eet:Hlavicka/@uuid_zpravy/data(.)");
q.setQuery(ms_nsDef + queryString);
q.evaluateTo(&result);
result = result.trimmed();
if (m_resut == nullptr)
{
m_resut = new EetResult(this);
}
m_resut->setUuid(QUuid(result));
queryString = "//senv:Envelope/senv:Body/eet:Odpoved/eet:Hlavicka/@dat_prij/data(.)";
q.setQuery(ms_nsDef + queryString);
q.evaluateTo(&result);
result = result.trimmed();
m_resut->setReciveDate(QDateTime::fromString(result));
queryString = "//senv:Envelope/senv:Body/eet:Odpoved/eet:Potvrzeni/@fik/data(.)";
q.setQuery(ms_nsDef + queryString);
q.evaluateTo(&result);
result = result.trimmed();
m_resut->setFik(result);
QXmlResultItems items;
queryString = "//senv:Envelope/senv:Body/eet:Odpoved/eet:Varovani";
q.setQuery(ms_nsDef + queryString);
q.evaluateTo(&items);
EetMessageList warnings;
QXmlItem item = items.next();
while (!item.isNull())
{
EetMessage *mesg = new EetMessage(m_resut);
queryString = "./@kod_varov/data(.)";
q.setQuery(ms_nsDef + queryString);
q.setFocus(item);
q.evaluateTo(&result);
result = result.trimmed();
mesg->setCode(result.toInt());
queryString = "./text(.)";
q.setQuery(ms_nsDef + queryString);
q.setFocus(item);
q.evaluateTo(&result);
result = result.trimmed();
mesg->setMessage(result);
warnings.append(mesg);
item = items.next();
}
m_resut->setWarnings(warnings);
queryString = "//senv:Envelope/senv:Body/eet:Odpoved/eet:Chyba";
q.setQuery(ms_nsDef + queryString);
q.evaluateTo(&items);
EetMessageList errors;
item = items.next();
while (!item.isNull())
{
EetMessage *mesg = new EetMessage(m_resut);
queryString = "./@kod/data(.)";
q.setQuery(ms_nsDef + queryString);
q.setFocus(item);
q.evaluateTo(&result);
result = result.trimmed();
mesg->setCode(result.toInt());
queryString = "./text(.)";
q.setQuery(ms_nsDef + queryString);
q.setFocus(item);
q.evaluateTo(&result);
result = result.trimmed();
mesg->setMessage(result);
errors.append(mesg);
item = items.next();
}
m_resut->setErrors(errors);
emit responseRecieved(m_resut);
reply->deleteLater();
}

@ -6,6 +6,10 @@
#include "eetcpp_global.h"
#include "eetrequest.h"
#include "eettemplate.h"
#include "eetresult.h"
class QNetworkAccessManager;
class QNetworkReply;
class EETCPPSHARED_EXPORT EetSender : public QObject
{
@ -16,13 +20,29 @@ public:
void sendRequest(EetRequest *request);
void setupSigner(const QString &certPath, const QString &passwd);
void setCheckSignature(bool checkSignature);
bool checkSignature() const;
EetResult *resut() const;
private:
static const QString ms_nsDef;
EetSigner *m_signer;
QNetworkAccessManager *m_manager;
bool m_checkSignature;
EetResult *m_resut;
bool verifySignature(const QByteArray &repData);
private slots:
void replyFinished(QNetworkReply *reply);
signals:
void certError();
void sendError();
void responseRecieved();
void responseRecieved(EetRequest *result);
void signInvalid();
void serviceCertError();
public slots:
};

@ -69,10 +69,17 @@ QString EetTemplate::fillTemplateInternal(EetRequest *request, QMap<QString, QSt
{
QChar c = m_template[i];
if (!m_template.mid(i).startsWith(phStart))
{
if ((i > 0 && c == ' ' && m_template[i - 1] == ' '))
{
continue;
}
else
{
ret += c;
continue;
}
}
int p = m_template.indexOf("}", i + 2);
if (p < 0)
@ -111,7 +118,7 @@ QString EetTemplate::fillTemplateInternal(EetRequest *request, QMap<QString, QSt
i = p;
}
return ret;
return ret.replace(QRegExp("\" >"), "\">");
}
QString EetTemplate::getPkpString(EetRequest *request)

@ -4,7 +4,7 @@
#
#-------------------------------------------------
QT += network xml
QT += network xml xmlpatterns
QT -= gui
@ -19,14 +19,16 @@ SOURCES += eetcpp.cpp \
eetrequest.cpp \
eettemplate.cpp \
eetsender.cpp \
eetsigner.cpp
eetsigner.cpp \
eetresult.cpp
HEADERS += eetcpp.h\
eetcpp_global.h \
eetrequest.h \
eettemplate.h \
eetsender.h \
eetsigner.h
eetsigner.h \
eetresult.h
unix {
target.path = /usr/lib

@ -1,10 +1,10 @@
<soap:Body xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="TheBody" xml:id="TheBody">
<eet:Trzba xmlns:eet="http://fs.mfcr.cz/eet/schema/v3">
<eet:Hlavicka @{dat_odesl} @{overeni} @{prvni_zaslani} @{uuid_zpravy}></eet:Hlavicka>
<eet:Data @{celk_trzba} @{cerp_zuct} @{cest_sluz} @{dan1} @{dan2} @{dan3} @{dat_trzby} @{dic_popl} @{dic_poverujiciho} @{id_pokl} @{id_provoz} @{porad_cis} @{pouzit_zboz1} @{pouzit_zboz2} @{pouzit_zboz3} @{rezim} @{urceno_cerp_zuct} @{zakl_dan1} @{zakl_dan2} @{zakl_dan3} @{zakl_nepodl_dph}></eet:Data>
<eet:KontrolniKody>
<eet:pkp cipher="RSA2048" digest="SHA256" encoding="base64">${pkp}</eet:pkp>
<eet:bkp digest="SHA1" encoding="base16">${bkp}</eet:bkp>
</eet:KontrolniKody>
</eet:Trzba>
</soap:Body>
<eet:Trzba xmlns:eet="http://fs.mfcr.cz/eet/schema/v3">
<eet:Hlavicka @{dat_odesl} @{overeni} @{prvni_zaslani} @{uuid_zpravy}></eet:Hlavicka>
<eet:Data @{celk_trzba} @{cerp_zuct} @{cest_sluz} @{dan1} @{dan2} @{dan3} @{dat_trzby} @{dic_popl} @{dic_poverujiciho} @{id_pokl} @{id_provoz} @{porad_cis} @{pouzit_zboz1} @{pouzit_zboz2} @{pouzit_zboz3} @{rezim} @{urceno_cerp_zuct} @{zakl_dan1} @{zakl_dan2} @{zakl_dan3} @{zakl_nepodl_dph}></eet:Data>
<eet:KontrolniKody>
<eet:pkp cipher="RSA2048" digest="SHA256" encoding="base64">${pkp}</eet:pkp>
<eet:bkp digest="SHA1" encoding="base16">${bkp}</eet:bkp>
</eet:KontrolniKody>
</eet:Trzba>
</soap:Body>

@ -10,20 +10,20 @@
ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3"
wsu:Id="TheCert">${certb64}</wsse:BinarySecurityToken>
<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#" Id="TheSignature">
<ds:SignedInfo>
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
<ec:InclusiveNamespaces xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#" PrefixList="soap"/>
</ds:CanonicalizationMethod>
<ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>
<ds:Reference URI="#TheBody">
<ds:Transforms>
<ds:Transform Algorithm='http://www.w3.org/2001/10/xml-exc-c14n#'/>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
<ds:DigestValue>${digest}</ds:DigestValue><!--computed by xmldig engine -->
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue>${signature}</ds:SignatureValue><!--computed by xmldig engine -->
<ds:SignedInfo>
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
<ec:InclusiveNamespaces xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#" PrefixList="soap"/>
</ds:CanonicalizationMethod>
<ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>
<ds:Reference URI="#TheBody">
<ds:Transforms>
<ds:Transform Algorithm='http://www.w3.org/2001/10/xml-exc-c14n#'/>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
<ds:DigestValue>${digest}</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue>${signature}</ds:SignatureValue>
<ds:KeyInfo Id="TheKeyInfo">
<wsse:SecurityTokenReference wsu:Id="TheSecurityTokenReference">
<wsse:Reference URI="#TheCert" ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3"/>
@ -32,5 +32,5 @@
</ds:Signature>
</wsse:Security>
</SOAP-ENV:Header>
${soap:Body}
${soap:Body}
</soap:Envelope>

@ -1,13 +1,13 @@
<ds:SignedInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
<ec:InclusiveNamespaces xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#" PrefixList="soap"></ec:InclusiveNamespaces>
</ds:CanonicalizationMethod>
<ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"></ds:SignatureMethod>
<ds:Reference URI="#TheBody">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"></ds:Transform>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></ds:DigestMethod>
<ds:DigestValue>${digest}</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
<ec:InclusiveNamespaces xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#" PrefixList="soap"></ec:InclusiveNamespaces>
</ds:CanonicalizationMethod>
<ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"></ds:SignatureMethod>
<ds:Reference URI="#TheBody">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"></ds:Transform>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></ds:DigestMethod>
<ds:DigestValue>${digest}</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
Loading…
Cancel
Save