Files
EetCpp/tests/eetv4client_integration_test.cpp
T

140 lines
5.8 KiB
C++

#include "eetv4client.h"
#include "eetv4signer.h"
#include <QFile>
#include <QProcess>
#include <QSslCertificate>
#include <QSslKey>
#include <QSslServer>
#include <QTemporaryDir>
#include <QtTest>
namespace
{
class MockEetServer : public QSslServer
{
public:
explicit MockEetServer(const QByteArray &response)
: m_response(response)
{
connect(this, &QSslServer::pendingConnectionAvailable, this, [this] {
QSslSocket *socket = qobject_cast<QSslSocket *>(nextPendingConnection());
if (socket == nullptr)
{
return;
}
connect(socket, &QSslSocket::readyRead, this, [this, socket] {
const QByteArray request = socket->readAll();
const qsizetype bodyStart = request.indexOf("\r\n\r\n");
const QByteArray soap = bodyStart < 0 ? QByteArray()
: request.mid(bodyStart + 4);
QString verificationError;
m_requestVerified = !soap.isEmpty() &&
EetV4Signer::verifySoap(soap, &verificationError);
const QByteArray http =
"HTTP/1.1 200 OK\r\nContent-Type: text/xml; charset=utf-8\r\n"
"Content-Length: " + QByteArray::number(m_response.size()) +
"\r\nConnection: close\r\n\r\n" + m_response;
socket->write(http);
socket->disconnectFromHost();
});
});
}
bool requestVerified() const
{
return m_requestVerified;
}
private:
QByteArray m_response;
bool m_requestVerified{false};
};
}
class EetV4ClientIntegrationTest : public QObject
{
Q_OBJECT
private slots:
void sendsSignedSaleAndParsesPok();
};
void EetV4ClientIntegrationTest::sendsSignedSaleAndParsesPok()
{
QTemporaryDir directory;
QVERIFY(directory.isValid());
const QString keyPath = directory.filePath(QStringLiteral("key.pem"));
const QString certPath = directory.filePath(QStringLiteral("certificate.pem"));
const QString p12Path = directory.filePath(QStringLiteral("certificate.p12"));
auto runOpenSsl = [](const QStringList &arguments) {
QProcess process;
process.start(QStringLiteral("openssl"), arguments);
QVERIFY2(process.waitForFinished(30000), qPrintable(process.errorString()));
QVERIFY2(process.exitStatus() == QProcess::NormalExit && process.exitCode() == 0,
process.readAllStandardError().constData());
};
runOpenSsl({QStringLiteral("req"), QStringLiteral("-x509"), QStringLiteral("-newkey"),
QStringLiteral("rsa:2048"), QStringLiteral("-nodes"), QStringLiteral("-subj"),
QStringLiteral("/CN=localhost"), QStringLiteral("-keyout"), keyPath,
QStringLiteral("-out"), certPath, QStringLiteral("-days"), QStringLiteral("1")});
runOpenSsl({QStringLiteral("pkcs12"), QStringLiteral("-export"), QStringLiteral("-out"),
p12Path, QStringLiteral("-inkey"), keyPath, QStringLiteral("-in"), certPath,
QStringLiteral("-passout"), QStringLiteral("pass:test")});
const QByteArray unsignedResponse =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
"<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\""
" xmlns:wsse=\"http://docs.oasis-open.org/wss/2004/01/"
"oasis-200401-wss-wssecurity-secext-1.0.xsd\""
" xmlns:wsu=\"http://docs.oasis-open.org/wss/2004/01/"
"oasis-200401-wss-wssecurity-utility-1.0.xsd\">"
"<soap:Header/><soap:Body wsu:Id=\"response-body\">"
"<Odpoved xmlns=\"http://fs.gov.cz/eet/schema/v4\">"
"<Hlavicka uuid_zpravy=\"123e4567-e89b-42d3-a456-426614174000\" "
"dat_prij=\"2026-10-13T20:00:00+02:00\"/>"
"<Potvrzeni pok=\"123e4567-e89b-42d3-a456-426614174000-01\"/>"
"</Odpoved></soap:Body></soap:Envelope>";
QString signingError;
const QByteArray signedResponse = EetV4Signer::signSoap(
unsignedResponse, p12Path, QByteArrayLiteral("test"), &signingError);
QVERIFY2(!signedResponse.isEmpty(), qPrintable(signingError));
MockEetServer server(signedResponse);
QSslConfiguration serverSsl = QSslConfiguration::defaultConfiguration();
QFile keyFile(keyPath);
QFile certificateFile(certPath);
QVERIFY(keyFile.open(QIODevice::ReadOnly));
QVERIFY(certificateFile.open(QIODevice::ReadOnly));
serverSsl.setPrivateKey(QSslKey(keyFile.readAll(), QSsl::Rsa, QSsl::Pem));
serverSsl.setLocalCertificate(QSslCertificate(certificateFile.readAll(), QSsl::Pem));
server.setSslConfiguration(serverSsl);
QVERIFY(server.listen(QHostAddress::LocalHost));
QSslConfiguration clientSsl = QSslConfiguration::defaultConfiguration();
clientSsl.setCaCertificates({serverSsl.localCertificate()});
EetV4Client client({
QUrl(QStringLiteral("https://localhost:%1/eet").arg(server.serverPort())),
5000, clientSsl
});
EetV4SaleRequest request;
request.sentAt = QDateTime::currentDateTime().toOffsetFromUtc(0);
request.saleAt = request.sentAt;
request.taxpayerEic = QStringLiteral("CZ123456789");
request.unitId = 1;
request.cashRegisterId = QStringLiteral("KASA1");
request.receiptNumber = QStringLiteral("TEST-1");
QVERIFY(EetV4Amount::fromString(QStringLiteral("100.00"), &request.totalSale));
EetV4Response response;
QString error;
QVERIFY2(client.sendSale(request, p12Path, QByteArrayLiteral("test"), &response, &error),
qPrintable(error));
QVERIFY(server.requestVerified());
QVERIFY(response.isSuccess());
QCOMPARE(response.pok, QStringLiteral("123e4567-e89b-42d3-a456-426614174000-01"));
}
QTEST_MAIN(EetV4ClientIntegrationTest)
#include "eetv4client_integration_test.moc"