1
0
forked from BRT/arc
arc/android/ziraat/PayByIbanScript.cpp
slava 2552ca49be Add Ziraat Bank integration and support for IBAN payments
This update introduces support for Ziraat Bank, including scripts for retrieving transaction history, parsing account information, and performing IBAN payments. Enhancements include improved screen parsing logic, additional transaction types, and better handling of amounts and IBAN-specific operations.
2025-06-17 18:13:29 +07:00

350 lines
16 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "PayByIbanScript.h"
#include <QRandomGenerator>
#include <QThread>
#include <utility>
#include "DatabaseManager.h"
#include "adb/AdbUtils.h"
#include "dao/AccountDAO.h"
#include "dao/ApplicationDAO.h"
#include "dao/DeviceDAO.h"
#include "dao/TransactionDAO.h"
#include "db/ApplicationInfo.h"
#include "db/DeviceInfo.h"
#include "time/DateUtils.h"
PayByIbanScript::PayByIbanScript(
AccountInfo account,
QString iban,
QString fullName,
const double amount,
QObject *parent
) : CommonZiraatScript(parent),
m_account(std::move(account)), m_iban(std::move(iban)),
m_fullName(std::move(fullName)), m_amount(amount) {
}
PayByIbanScript::~PayByIbanScript() = default;
void PayByIbanScript::makePayment(const DeviceInfo &device) {
// Оплата со страницы карты
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(device.id, ++m_counter));
Node editIbanEditText = xmlScreenParser.findEditTextByResourceId("com.ziraat.ziraatmobil:id/edit_iban");
Node fullNameEditText = xmlScreenParser.findEditTextByResourceId("com.ziraat.ziraatmobil:id/edit_full_name");
if (!editIbanEditText.isEmpty() && !fullNameEditText.isEmpty()) {
AdbUtils::makeTap(device.id, editIbanEditText.x(), editIbanEditText.y());
QThread::msleep(500);
AdbUtils::inputText(device.id, m_iban);
AdbUtils::makeTap(device.id, editIbanEditText.x(), editIbanEditText.y());
QThread::msleep(500);
AdbUtils::inputText(device.id, m_fullName);
Node nextBtn = xmlScreenParser.findButtonNode("NEXT", false);
AdbUtils::makeTap(device.id, nextBtn.x(), nextBtn.y());
bool findSenderAccount = false;
for (int i = 0; i < 5; ++i) {
QThread::msleep(1000);
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(device.id, ++m_counter));
Node senderAccount = xmlScreenParser.findTextNode("Sender Account");
if (!senderAccount.isEmpty()) {
Node inputBankName = xmlScreenParser.findAccountButton(m_account.lastNumbers);
if (!inputBankName.isEmpty()) {
AdbUtils::makeTap(device.id, inputBankName.x(), inputBankName.y());
QThread::msleep(500);
// FXIME скорее всего придется нажать кнопку NEXT
findSenderAccount = true;
}
break;
}
}
if (!findSenderAccount) {
m_error = "Не нашли Sender Account";
qDebug() << m_error;
return;
}
bool findAmountDetermination = false;
for (int i = 0; i < 5; ++i) {
QThread::msleep(1000);
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(device.id, ++m_counter));
Node amountDetermination = xmlScreenParser.findTextNode("Amount Determination");
if (!amountDetermination.isEmpty()) {
Node integerEditText = xmlScreenParser.findEditTextByResourceId(
"com.ziraat.ziraatmobil:id/edit_text_integer");
Node decimalEditText = xmlScreenParser.findEditTextByResourceId(
"com.ziraat.ziraatmobil:id/edit_text_decimal");
if (!integerEditText.isEmpty() && !decimalEditText.isEmpty()) {
int integerPart = static_cast<int>(m_amount);
AdbUtils::makeTap(device.id, integerEditText.x(), integerEditText.y());
QThread::msleep(500);
AdbUtils::inputText(device.id, QString::number(integerPart));
int decimalPart = static_cast<int>((m_amount - integerPart) * 100);
AdbUtils::makeTap(device.id, decimalEditText.x(), decimalEditText.y());
QThread::msleep(500);
AdbUtils::inputText(device.id, QString::number(decimalPart));
findAmountDetermination = true;
break;
} else {
m_error = "Не нашли поля ввода для ввода суммы перевода";
qDebug() << m_error;
return;
}
}
}
if (!findAmountDetermination) {
m_error = "Не нашли Amount Determination";
qDebug() << m_error;
return;
}
bool findDetailDefinition = false;
for (int i = 0; i < 5; ++i) {
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(device.id, ++m_counter));
Node fastTransferBtn = xmlScreenParser.findButtonNode("FAST TRANSFER", false);
if (!fastTransferBtn.isEmpty()) {
AdbUtils::makeTap(device.id, fastTransferBtn.x(), fastTransferBtn.y());
QThread::msleep(500);
continue;
}
Node detailDefinitionTitle = xmlScreenParser.findTextNode("Detail Definition");
Node pleaseChooseBtn = xmlScreenParser.findButtonNode("Please choose", false);
if (!detailDefinitionTitle.isEmpty() && !pleaseChooseBtn.isEmpty()) {
AdbUtils::makeTap(device.id, pleaseChooseBtn.x(), pleaseChooseBtn.y());
QThread::msleep(500);
Node searchEditText = xmlScreenParser.
findEditTextByResourceId("com.ziraat.ziraatmobil:id/input_search");
if (!searchEditText.isEmpty()) {
AdbUtils::makeTap(device.id, searchEditText.x(), searchEditText.y());
QThread::msleep(500);
AdbUtils::inputText(device.id, "Other Payments");
QThread::msleep(1000);
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(device.id, ++m_counter));
Node otherPaymentsText = xmlScreenParser.findTextNode("Other Payments");
if (!otherPaymentsText.isEmpty()) {
AdbUtils::makeTap(device.id, otherPaymentsText.x(), otherPaymentsText.y());
QThread::msleep(500);
findDetailDefinition = true;
break;
}
} else {
for (int i = 0; i < 5; ++i) {
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(device.id, ++m_counter));
Node otherPaymentsText = xmlScreenParser.findTextNode("Other Payments");
if (otherPaymentsText.isEmpty()) {
AdbUtils::makeSwipe(
m_account.deviceId,
device.screenWidth / 2, device.screenHeight / 4 * 3,
device.screenWidth / 2, device.screenHeight / 4
);
} else {
AdbUtils::makeTap(device.id, otherPaymentsText.x(), otherPaymentsText.y());
QThread::msleep(500);
findDetailDefinition = true;
break;
}
QThread::msleep(500);
}
}
}
}
if (!findDetailDefinition) {
m_error = "Не нашли Detail Definition";
qDebug() << m_error;
return;
}
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(device.id, ++m_counter));
Node nextBtn4 = xmlScreenParser.findButtonNode("NEXT", false);
AdbUtils::makeTap(device.id, nextBtn4.x(), nextBtn4.y());
QThread::msleep(500);
Node checkInfo = xmlScreenParser.findTextNode(
"Check the details of the transaction you shall realize and approve your transaction.");
if (!checkInfo.isEmpty()) {
for (int i = 0; i < 5; ++i) {
Node confirmBtn = xmlScreenParser.findButtonNode("CONFIRM", false);
if (confirmBtn.isEmpty()) {
AdbUtils::makeSwipe(
m_account.deviceId,
device.screenWidth / 2, device.screenHeight / 4 * 3,
device.screenWidth / 2, device.screenHeight / 4
);
} else {
AdbUtils::makeTap(device.id, confirmBtn.x(), confirmBtn.y());
QThread::msleep(500);
break;
}
QThread::msleep(500);
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(device.id, ++m_counter));
}
QThread::msleep(1000);
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(device.id, ++m_counter));
Node successText = xmlScreenParser.findTextNode("Your transaction is successfully realized.");
if (!successText.isEmpty()) {
Node receiptBtn = xmlScreenParser.findButtonNode("RECEIPT", false);
if (!receiptBtn.isEmpty()) {
AdbUtils::makeTap(device.id, receiptBtn.x(), receiptBtn.y());
QThread::msleep(500);
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(device.id, ++m_counter));
Node sendBtn = xmlScreenParser.findButtonNode("SEND E-MAIL", false);
if (!sendBtn.isEmpty()) {
AdbUtils::takeXmlDump(
device.id, "pay_by_iban_finish_transactions_" + QString::number(m_account.id)
);
// Успешная транзакция
// TODO считываем все данные по переводу
TransactionInfo transaction;
transaction.name = m_fullName;
transaction.accountId = m_account.id;
transaction.amount = -m_amount;
transaction.fee = 0;
transaction.status = TransactionStatus::Complete;
transaction.type = TransactionType::Iban;
transaction.updateTime = DateUtils::getUtcNow();
transaction.completeTime = DateUtils::getUtcNow();
transaction.timestamp = DateUtils::getUtcNow();
transaction.id = TransactionDAO::insertTransaction(transaction);
if (transaction.id == -1) {
// FIXME alert!!
qDebug() << "Transaction has not inserted...";
}
postNewTransactionData(m_account, transaction);
Node backBtn = xmlScreenParser.findButtonNode("BACK", false);
if (!backBtn.isEmpty()) {
AdbUtils::makeTap(device.id, backBtn.x(), backBtn.y());
QThread::msleep(500);
Node returnBtn = xmlScreenParser.findButtonNode("RETURN TO HOME PAGE", false);
if (!returnBtn.isEmpty()) {
AdbUtils::makeTap(device.id, returnBtn.x(), returnBtn.y());
}
}
} else {
//FIXME не успешная транзакция
AdbUtils::takeXmlDump(
device.id, "pay_by_iban_fail_transactions_receipt_" + QString::number(m_account.id)
);
m_error = "Транзакция не успешна";
qDebug() << m_error;
return;
}
}
} else {
m_error = "Транзакция не успешна";
qDebug() << m_error;
return;
}
} else {
m_error = "Не нашли Check the details title info";
qDebug() << m_error;
return;
}
} else {
m_error = "Не нашли поля ввода для IBAN";
qDebug() << m_error;
return;
}
}
void PayByIbanScript::doStart() {
const DeviceInfo device = DeviceDAO::getDeviceById(m_account.deviceId);
const ApplicationInfo app = ApplicationDAO::getApplication(m_account.deviceId, m_account.appCode);
if (device.id.isEmpty() || app.id == -1) {
m_error = "Device or app not found.";
qDebug() << m_error;
emit finishedWithResult(m_error);
return;
}
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(m_account.deviceId, ++m_counter));
if (!xmlScreenParser.isHomeScreen()) {
if (!runAppAndGoToHomeScreen(device.id, app.package, app.pinCode, device.screenWidth, device.screenHeight)) {
m_error = "Не смогли дойти до домашней страницы";
qDebug() << m_error;
emit finishedWithResult(m_error);
return;
}
}
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(m_account.deviceId, ++m_counter));
Node allTransactionsNav = xmlScreenParser.findTextNode("Transactions");
if (!allTransactionsNav.isEmpty()) {
AdbUtils::makeTap(device.id, allTransactionsNav.x(), allTransactionsNav.y());
QThread::msleep(1000);
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(m_account.deviceId, ++m_counter));
// перешли на страницу транзакций
Node allTransactionsTitle = xmlScreenParser.findTextNode(
"Transactions", 0, 0, device.screenWidth, device.screenHeight / 2
);
Node moneyTransfersBtn = xmlScreenParser.findTextNode("Money Transfers");
if (!allTransactionsTitle.isEmpty() && !moneyTransfersBtn.isEmpty()) {
AdbUtils::makeTap(device.id, moneyTransfersBtn.x(), moneyTransfersBtn.y());
QThread::msleep(1000);
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(m_account.deviceId, ++m_counter));
// перешли на страницу переводов
Node moneyTransfersTitle = xmlScreenParser.findTextNode(
"Money Transfers", 0, 0, device.screenWidth, device.screenHeight / 2
);
Node transferToOtherAccountBtn = xmlScreenParser.findTextNode("Transfer to Other Account");
if (!moneyTransfersTitle.isEmpty() && !transferToOtherAccountBtn.isEmpty()) {
AdbUtils::makeTap(device.id, transferToOtherAccountBtn.x(), transferToOtherAccountBtn.y());
QThread::msleep(1000);
xmlScreenParser.parseAndSaveXml(AdbUtils::getScreenDumpAsXml(m_account.deviceId, ++m_counter));
Node transferToOtherAccountTitle = xmlScreenParser.findTextNode(
"Transfer to Other Account", 0, 0, device.screenWidth, device.screenHeight / 2
);
Node aNewRecipientBtn = xmlScreenParser.findTextNode("A New Recipient");
if (!transferToOtherAccountTitle.isEmpty() && !aNewRecipientBtn.isEmpty()) {
AdbUtils::makeTap(device.id, aNewRecipientBtn.x(), aNewRecipientBtn.y());
QThread::msleep(1000);
makePayment(device);
} else {
m_error = "Не нашли кнопку 'A New Recipient'";
qDebug() << m_error;
}
} else {
m_error = "Не нашли кнопку 'Transfer to Other Account'";
qDebug() << m_error;
}
} else {
m_error = "Не нашли кнопку 'Money Transfers'";
qDebug() << m_error;
}
} else {
m_error = "Не нашли пункт меню 'Transactions'";
qDebug() << m_error;
}
if (!m_error.isEmpty()) {
AdbUtils::takeXmlDump(device.id, "pay_by_iban_fail_transactions_" + QString::number(m_account.id));
}
emit finishedWithResult(m_error);
}