Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 57 additions & 26 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
I've updated the README.md to include instructions for using FetchContent to include the BankID library in a CMake project, covering both static and dynamic linking options. Below is the updated README content, followed by instructions to download it as a file.

---

# BankID C++ Library and Server

<div align="center">
Expand Down Expand Up @@ -217,18 +213,18 @@ FetchContent_MakeAvailable(bankid)

# Static Linking
add_executable(main_static main.cpp)
target_link_libraries(main_static PRIVATE BankID::bankid_lib)
target_link_libraries(main_static PRIVATE BankID::bankid)
target_compile_definitions(main_static PRIVATE BANKID_STATIC)

# Dynamic Linking
add_executable(main_dynamic main.cpp)
target_link_libraries(main_dynamic PRIVATE BankID::bankid_lib)
target_link_libraries(main_dynamic PRIVATE BankID::bankid)

# Copy DLL to output directory for dynamic linking (Windows)
if(WIN32)
add_custom_command(TARGET main_dynamic POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
$<TARGET_FILE:BankID::bankid_lib>
$<TARGET_FILE:BankID::bankid>
$<TARGET_FILE_DIR:main_dynamic>
)
endif()
Expand Down Expand Up @@ -460,10 +456,13 @@ int main() {
int main() {
// Sign a document
BankID::SSLConfig sslConfig(BankID::Environment::TEST);
BankID::Session session(sslConfig, true);
bool debug = true;
BankID::Session session(sslConfig, debug);

BankID::API::SignConfig signConfig("192.168.1.1", BankID::Base64::encode("This is a encoded message"));
signConfig.setUserVisibleData("Please sign this document");
BankID::API::SignConfig signConfig("192.168.1.1", BankID::Base64::encode("This is a user visible message"));
signConfig.setUserNonVisibleData(BankID::Base64::encode("This is non-visible data"))
.setReturnUrl("https://example.com/return")
.setUserVisibleDataFormat("plaintext");

auto signResult = session.sign(signConfig);
if (signResult.has_value()) {
Expand Down Expand Up @@ -584,6 +583,26 @@ int main() {
}
}

// Seleep for 2 seconds to simulate some processing
std::this_thread::sleep_for(std::chrono::seconds(2));

// Print the next QR code again
if (generator) {
auto nextCode = generator->getNextQRCode();
if (nextCode.has_value()) {
std::cout << "Next QR Code after 2 seconds: " << nextCode.value() << std::endl;
} else {
std::cout << "Failed to get next QR Code: " << nextCode.error().errorCode << " - " << nextCode.error().details << std::endl;
}
}

// Check if the generator is expired
if (generator && generator->isExpired()) {
std::cout << "QR Code generator has expired." << std::endl;
} else {
std::cout << "QR Code generator is still valid." << std::endl;
}

// Remove from cache when done
cache.remove(orderRef);
return 0;
Expand All @@ -597,46 +616,58 @@ int main() {
#include <iostream>
#include <thread>

int main() {
int main()
{
BankID::SSLConfig sslConfig(BankID::Environment::TEST);
BankID::Session session(sslConfig, true);

BankID::API::AuthConfig authConfig("192.168.1.1");
auto authResult = session.auth(authConfig);

if (authResult.has_value()) {
// Add to QR cache
auto& qrCache = BankID::QRGeneratorCache::instance();
qrCache.add(authResult->orderRef,
authResult->qrStartToken,
authResult->qrStartSecret);
if (authResult.has_value())
{
// Getting automatic QR code cache generated by the BankID library
auto qrGenerator = BankID::QRGeneratorCache::instance().get(authResult->orderRef);

// Generate QR codes while polling
BankID::API::CollectConfig collectConfig(authResult->orderRef);
auto qrGenerator = qrCache.get(authResult->orderRef);

while (true) {
while (true)
{
// Check authentication status
auto collectResult = session.collect(collectConfig);

// Generate new QR code
if (qrGenerator && !qrGenerator->isExpired()) {
if (qrGenerator && !qrGenerator->isExpired())
{
auto qrCode = qrGenerator->getNextQRCode();
if (qrCode.has_value()) {
if (qrCode.has_value())
{
// Display new QR code to user (simulated here)
std::cout << "QR Code: " << qrCode.value() << std::endl;
}
}
else
{
BankID::QRGeneratorCache::instance().remove(collectResult->orderRef);
BankID::QRGeneratorCache::instance().shutdown();
std::cout << "QR Code expired, you will need to refresh the authentication and start a new session." << std::endl;
return 1; // Exit if QR code is expired
}

if (collectResult.has_value() && collectResult->status == BankID::API::CollectStatus::COMPLETE) {
qrCache.remove(authResult->orderRef);
if (collectResult.has_value() && collectResult->status == BankID::API::CollectStatus::COMPLETE)
{
BankID::QRGeneratorCache::instance().remove(collectResult->orderRef);
std::cout << "Authentication completed!" << std::endl;
break;
}

std::this_thread::sleep_for(std::chrono::seconds(1));
}
}

BankID::QRGeneratorCache::instance().shutdown();

return 0;
}
```
Expand Down Expand Up @@ -745,7 +776,7 @@ FetchContent_MakeAvailable(bankid)

# Static linking
add_executable(my_app main.cpp)
target_link_libraries(my_app PRIVATE BankID::bankid_lib)
target_link_libraries(my_app PRIVATE BankID::bankid)
target_compile_definitions(my_app PRIVATE BANKID_STATIC)
```

Expand Down Expand Up @@ -784,13 +815,13 @@ FetchContent_MakeAvailable(bankid)

# Dynamic linking
add_executable(my_app main.cpp)
target_link_libraries(my_app PRIVATE BankID::bankid_lib)
target_link_libraries(my_app PRIVATE BankID::bankid)

# Copy DLL to output directory (Windows)
if(WIN32)
add_custom_command(TARGET my_app POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
$<TARGET_FILE:BankID::bankid_lib>
$<TARGET_FILE:BankID::bankid>
$<TARGET_FILE_DIR:my_app>
)
endif()
Expand Down
15 changes: 12 additions & 3 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ add_executable(bankid_tests
test_sign.cpp
test_payment.cpp
test_other_payment.cpp
# test_phone_auth.cpp
# test_phone_sign.cpp
# test_collect.cpp
test_phone_auth.cpp
test_phone_sign.cpp
test_collect.cpp
test_cancel.cpp
)

Expand Down Expand Up @@ -131,6 +131,15 @@ set_tests_properties(PaymentTests PROPERTIES WORKING_DIRECTORY $<TARGET_FILE_DIR
add_test(NAME OtherPaymentTests COMMAND bankid_tests --gtest_filter=OtherPaymentTest.*)
set_tests_properties(OtherPaymentTests PROPERTIES WORKING_DIRECTORY $<TARGET_FILE_DIR:bankid_tests>)

add_test(NAME PhoneAuthTests COMMAND bankid_tests --gtest_filter=PhoneAuthTest.*)
set_tests_properties(PhoneAuthTests PROPERTIES WORKING_DIRECTORY $<TARGET_FILE_DIR:bankid_tests>)

add_test(NAME PhoneSignTests COMMAND bankid_tests --gtest_filter=PhoneSignTest.*)
set_tests_properties(PhoneSignTests PROPERTIES WORKING_DIRECTORY $<TARGET_FILE_DIR:bankid_tests>)

add_test(NAME CollectTests COMMAND bankid_tests --gtest_filter=CollectTest.*)
set_tests_properties(CollectTests PROPERTIES WORKING_DIRECTORY $<TARGET_FILE_DIR:bankid_tests>)

add_test(NAME CancelTests COMMAND bankid_tests --gtest_filter=CancelTest.*)
set_tests_properties(CancelTests PROPERTIES WORKING_DIRECTORY $<TARGET_FILE_DIR:bankid_tests>)

Expand Down
160 changes: 160 additions & 0 deletions tests/test_collect.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
#include <gtest/gtest.h>
#include <gmock/gmock.h>
#include "bankid.h"
#include "api/auth.h"
#include "api/responses.h"

class CollectTest : public ::testing::Test
{
public:
CollectTest()
: sslConfig(BankID::Environment::TEST),
session(std::make_unique<BankID::Session>(sslConfig))
{
}

protected:
void TearDown() override
{
session.reset();
}

void CancelOrder(std::string orderRef)
{
BankID::API::CancelConfig cancelConfig(orderRef);
auto cancelResponse = session->cancel(cancelConfig);
EXPECT_TRUE(cancelResponse.has_value());
EXPECT_EQ(cancelResponse.value().httpStatus, 200);
}

BankID::SSLConfig sslConfig;
std::unique_ptr<BankID::Session> session;
};

TEST_F(CollectTest, CollectAuth)
{
BankID::API::AuthConfig config("127.0.0.1");

EXPECT_TRUE(config.getReturnUrl().value_or("").empty());
EXPECT_TRUE(config.getUserVisibleData().value_or("").empty());

// Make the API call
auto response = session->auth(config);

EXPECT_TRUE(response.has_value());

// Check the response
const auto &orderResponse = response.value();
EXPECT_EQ(orderResponse.httpStatus, 200);
EXPECT_FALSE(orderResponse.orderRef.empty());

BankID::API::CollectConfig collectConfig(orderResponse.orderRef);

auto collectResponse = session->collect(collectConfig);
EXPECT_TRUE(collectResponse.has_value());
EXPECT_EQ(collectResponse.value().httpStatus, 200);
EXPECT_EQ(collectResponse.value().orderRef, orderResponse.orderRef);
EXPECT_EQ(collectResponse.value().status, BankID::API::CollectStatus::PENDING);

BankID::API::CancelConfig cancelConfig(orderResponse.orderRef);
auto cancelResponse = session->cancel(cancelConfig);
EXPECT_TRUE(cancelResponse.has_value());
EXPECT_EQ(cancelResponse.value().httpStatus, 200);

collectResponse = session->collect(collectConfig);

EXPECT_FALSE(collectResponse.has_value());

if (!collectResponse.has_value())
{
EXPECT_EQ(collectResponse.error().details, R"({"errorCode":"invalidParameters","details":"No such order"})");
EXPECT_EQ(collectResponse.error().errorCode, BankID::BankIdErrorCode::INVALID_PARAMETERS);
EXPECT_EQ(collectResponse.error().httpStatus, 400);
}
};

TEST_F(CollectTest, CollectSign)
{
BankID::API::SignConfig config("127.0.0.1", BankID::Base64::encode("Test userVisibleData data"));
config.setUserVisibleDataFormat("simpleMarkdownV1");
EXPECT_TRUE(config.getReturnUrl().value_or("").empty());
EXPECT_EQ(config.getUserVisibleData(), BankID::Base64::encode("Test userVisibleData data"));

// Make the API call
auto response = session->sign(config);
EXPECT_TRUE(response.has_value());

// Check the response
const auto &orderResponse = response.value();
EXPECT_EQ(orderResponse.httpStatus, 200);
EXPECT_FALSE(orderResponse.orderRef.empty());
EXPECT_FALSE(orderResponse.autoStartToken.empty());

// Collect the order
BankID::API::CollectConfig collectConfig(orderResponse.orderRef);
auto collectResponse = session->collect(collectConfig);
EXPECT_TRUE(collectResponse.has_value());
EXPECT_EQ(collectResponse.value().httpStatus, 200);
EXPECT_EQ(collectResponse.value().orderRef, orderResponse.orderRef);
EXPECT_EQ(collectResponse.value().status, BankID::API::CollectStatus::PENDING);

// Cancel the order
BankID::API::CancelConfig cancelConfig(orderResponse.orderRef);
auto cancelResponse = session->cancel(cancelConfig);
EXPECT_TRUE(cancelResponse.has_value());
EXPECT_EQ(cancelResponse.value().httpStatus, 200);

// Try to collect again after cancellation
collectResponse = session->collect(collectConfig);
EXPECT_FALSE(collectResponse.has_value());

if (!collectResponse.has_value())
{
EXPECT_EQ(collectResponse.error().details, R"({"errorCode":"invalidParameters","details":"No such order"})");
EXPECT_EQ(collectResponse.error().errorCode, BankID::BankIdErrorCode::INVALID_PARAMETERS);
EXPECT_EQ(collectResponse.error().httpStatus, 400);
}
};

TEST_F(CollectTest, CollectPhoneSign)
{
BankID::API::PhoneSignConfig config("RP", BankID::Base64::encode("Test userVisibleData data"));
config.setUserVisibleDataFormat("simpleMarkdownV1");
config.setPersonalNumber("200003121145");

EXPECT_EQ(config.getUserVisibleData(), BankID::Base64::encode("Test userVisibleData data"));

// Make the API call
auto response = session->phoneSign(config);
EXPECT_TRUE(response.has_value());

// Check the response
const auto &orderResponse = response.value();
EXPECT_EQ(orderResponse.httpStatus, 200);
EXPECT_FALSE(orderResponse.orderRef.empty());

// Collect the order
BankID::API::CollectConfig collectConfig(orderResponse.orderRef);
auto collectResponse = session->collect(collectConfig);
EXPECT_TRUE(collectResponse.has_value());
EXPECT_EQ(collectResponse.value().httpStatus, 200);
EXPECT_EQ(collectResponse.value().orderRef, orderResponse.orderRef);
EXPECT_EQ(collectResponse.value().status, BankID::API::CollectStatus::PENDING);

// Cancel the order
BankID::API::CancelConfig cancelConfig(orderResponse.orderRef);
auto cancelResponse = session->cancel(cancelConfig);
EXPECT_TRUE(cancelResponse.has_value());
EXPECT_EQ(cancelResponse.value().httpStatus, 200);

// Try to collect again after cancellation
collectResponse = session->collect(collectConfig);
EXPECT_FALSE(collectResponse.has_value());

if (!collectResponse.has_value())
{
EXPECT_EQ(collectResponse.error().details, R"({"errorCode":"invalidParameters","details":"No such order"})");
EXPECT_EQ(collectResponse.error().errorCode, BankID::BankIdErrorCode::INVALID_PARAMETERS);
EXPECT_EQ(collectResponse.error().httpStatus, 400);
}
};
2 changes: 1 addition & 1 deletion tests/test_other_payment.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,7 @@ TEST_F(OtherPayment, PersonalNumberOtherPaymentAlreadyInProgress)
BankID::API::OtherPaymentConfig config("200001010101", transaction);

BankID::Requirement requirement;
requirement.personalNumber = "200003121145";
requirement.personalNumber = "200003121155";

config.setRequirement(requirement);

Expand Down
2 changes: 1 addition & 1 deletion tests/test_payment.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -356,7 +356,7 @@ TEST_F(Payment, PersonalNumberPaymentAlreadyInProgress)
BankID::API::PaymentConfig config("127.0.0.1", transaction);

BankID::Requirement requirement;
requirement.personalNumber = "200003121145";
requirement.personalNumber = "200003121165";

config.setRequirement(requirement);

Expand Down
Loading