first commit

This commit is contained in:
R5600U_PC 2024-05-17 15:38:38 +09:00
commit a2e3b46cdf
17 changed files with 1608 additions and 0 deletions

12
.gitignore vendored Normal file
View File

@ -0,0 +1,12 @@
Lib/
libs/
Scripts/
build/
dist/
Include/
__pycache__/
*.log
*.log.*
*.xlsx
pyvenv.cfg
.ssh/

57
config.ini Normal file
View File

@ -0,0 +1,57 @@
[DEFAULT]
max_businesses = 5
log_level = DEBUG
business_count = 0
encryption_key = UDHoVlNcjDeR7ABRyDVr349RAtEUBNMZH5w4cq8g2IM=
[USER]
user_id = leensoo1nt@gmail.com
password = gAAAAABmRrpwomEeVDrsgzi7afYKMZg0-B3eS3eZJrZGMTQ_FOebl-Uq2KkY6XByMAtr0hbGX0_ZiOgcIVSrEOf-9q7_Et38mA==
[BUSINESS_1]
사업자별칭 = sample_alias_1
사업자등록번호 = 123-45-67890
상호명 = sample_name_1
등록날짜 = 2023-01-01
응대전화번호 = 010-1234-5678
쿠팡_쿠팡id = gAAAAABmRvruHmgHV1k6kuaWXu_abhE5WcPZxMjW3QKK7jY9Ms3UT1nD0BgpH_ujpnThATcfc4QNhlOTcYpa7PB8psJIr1_BsnTQ4HGUI45VbBPnEoWGglU=
쿠팡_업체 코드 = gAAAAABmRvruW5eBP4UAE126L4DRScX9lgspb7ANxG-tdJOYNOg4gXo7F-4Xe-9LnIbjvxjITK0rqoCjJfAK8AaZRrzFohmXpX8MwM44XzMuyayC4WKsTu4=
쿠팡_access key = gAAAAABmRvruIlRrsIgwTSsR3fCYMM6G-hYerYMnFkSD050WM9WArprzDJvAjVjxmiLYh6xXDHUxu31wFhJjiFwdcjOcwSvYkx55pAJRN7Crk0Pw80e_Spw=
쿠팡_secret key = gAAAAABmRvru_QY05u0XIShzeLHiUWbdbRbW_5ruEPOl-7adaxjQZXOewnOaODi9wDdR2aLQ9dp0UNkIAVWZzq-BYc8ovEQ6I5keVA9mCzCxx8SWbIvst7M=
스마트스토어_업로드항 스마트스토어 계정 = gAAAAABmRrpwomEeVDrsgzi7afYKMZg0-B3eS3eZJrZGMTQ_FOebl-Uq2KkY6XByMAtr0hbGX0_ZiOgcIVSrEOf-9q7_Et38mA==
스마트스토어_애플리케이션 id = gAAAAABmRvruEqawY-NssQNcQwEeOcRiGsiV0_QABw0IUhn-su02wAcyQ2X-At2sRla6tBK0HSDVZyGdCrrEIhlvTq_EbFE-HeNi8zaKdbGoPmnMhV5i9OE=
스마트스토어_애플리케이션 시크릿 = gAAAAABmRvruf3WXP0dWq9b-ykEu_e2h7V2D9xcDfSyYtXb19u57STPmnabKSrUJeDnCaq23oBBM89vXnGPyIuWSTX5wajNnYLjYY0e_J5Gp-Jon5wv0ICU=
옥션지마켓_옥션id = gAAAAABmRvruDCrmyG3EyInh86KIHrZt5JQK0rF8jvt6a3EOMfQCsUxfk7pZkY6xF34DvQmBLmqCcgifH8oBpFqUixE1_OHhQ6RwMcLAnk8ympBbEctGD4g=
옥션지마켓_g마켓 id = gAAAAABmRvruJgJvYqzSfSg0YIAAb5h3HQOBUbheMqUYGiNU1fSxVgCCyODezPe-Ejgn4yLNOqmsxLkolyMWJNd5v0QCuqz_SbJPebff9I3tQaXC7pMqO6w=
11번가-일반_api key = gAAAAABmRvrurEqGJf086Qs6TJYxIQXuiOV5gytNZ5Z6u7pRjFY9JY2IEMzxG-cg1cGTAv1XF_ilgDCEJmZHYxrlSRfkUdMtrA_uk8u0zjXcnKuoI85S2aE=
11번가-글로벌_api key = gAAAAABmRvruI-bQL9A7rB1Z-JzqSQYaXm--wll9GMW-ke0cGLdD5iy_3VatzNGSy9JhOI2He_dF6srQ7EGbre-zfZReeaI1XLJEk-Ze6SL5EKcJ6j7IsLA=
롯데온_api key = gAAAAABmRvrumkOok8QyAX4caHgkJDiifOmEpYCGG6zsqysBunDZFzmTd6Zbk_6tWWlyqxdXIQbqCbDPwHSPpM4yF_y8f9QB8gxrTg6bbF3rBzAFChPH-iU=
인터파크_상품상태재고수정 인증키 = gAAAAABmRrpwomEeVDrsgzi7afYKMZg0-B3eS3eZJrZGMTQ_FOebl-Uq2KkY6XByMAtr0hbGX0_ZiOgcIVSrEOf-9q7_Et38mA==
인터파크_상품상태재고수정 비밀키 = gAAAAABmRrpwomEeVDrsgzi7afYKMZg0-B3eS3eZJrZGMTQ_FOebl-Uq2KkY6XByMAtr0hbGX0_ZiOgcIVSrEOf-9q7_Et38mA==
인터파크_상품재고조회 인증키 = gAAAAABmRrpwomEeVDrsgzi7afYKMZg0-B3eS3eZJrZGMTQ_FOebl-Uq2KkY6XByMAtr0hbGX0_ZiOgcIVSrEOf-9q7_Et38mA==
인터파크_상품재고조회 비밀키 = gAAAAABmRrpwomEeVDrsgzi7afYKMZg0-B3eS3eZJrZGMTQ_FOebl-Uq2KkY6XByMAtr0hbGX0_ZiOgcIVSrEOf-9q7_Et38mA==
인터파크_상품정보조회 인증 = gAAAAABmRrpwomEeVDrsgzi7afYKMZg0-B3eS3eZJrZGMTQ_FOebl-Uq2KkY6XByMAtr0hbGX0_ZiOgcIVSrEOf-9q7_Et38mA==
인터파크_상품정보조회 비밀키 = gAAAAABmRrpwomEeVDrsgzi7afYKMZg0-B3eS3eZJrZGMTQ_FOebl-Uq2KkY6XByMAtr0hbGX0_ZiOgcIVSrEOf-9q7_Et38mA==
인터파크_상품수정 인증키 = gAAAAABmRrpwomEeVDrsgzi7afYKMZg0-B3eS3eZJrZGMTQ_FOebl-Uq2KkY6XByMAtr0hbGX0_ZiOgcIVSrEOf-9q7_Et38mA==
인터파크_상품수정 비밀키 = gAAAAABmRrpwomEeVDrsgzi7afYKMZg0-B3eS3eZJrZGMTQ_FOebl-Uq2KkY6XByMAtr0hbGX0_ZiOgcIVSrEOf-9q7_Et38mA==
인터파크_상품등록 인증키 = gAAAAABmRrpwomEeVDrsgzi7afYKMZg0-B3eS3eZJrZGMTQ_FOebl-Uq2KkY6XByMAtr0hbGX0_ZiOgcIVSrEOf-9q7_Et38mA==
인터파크_상품등록 비밀키 = gAAAAABmRrpwomEeVDrsgzi7afYKMZg0-B3eS3eZJrZGMTQ_FOebl-Uq2KkY6XByMAtr0hbGX0_ZiOgcIVSrEOf-9q7_Et38mA==
인터파크_반품배송지조회 인증키 = gAAAAABmRrpwomEeVDrsgzi7afYKMZg0-B3eS3eZJrZGMTQ_FOebl-Uq2KkY6XByMAtr0hbGX0_ZiOgcIVSrEOf-9q7_Et38mA==
인터파크_반품배송지조회 비밀키 = gAAAAABmRrpwomEeVDrsgzi7afYKMZg0-B3eS3eZJrZGMTQ_FOebl-Uq2KkY6XByMAtr0hbGX0_ZiOgcIVSrEOf-9q7_Et38mA==
인터파크_반품배송지등록 인증키 = gAAAAABmRrpwomEeVDrsgzi7afYKMZg0-B3eS3eZJrZGMTQ_FOebl-Uq2KkY6XByMAtr0hbGX0_ZiOgcIVSrEOf-9q7_Et38mA==
인터파크_반품배송지등록 비밀키 = gAAAAABmRrpwomEeVDrsgzi7afYKMZg0-B3eS3eZJrZGMTQ_FOebl-Uq2KkY6XByMAtr0hbGX0_ZiOgcIVSrEOf-9q7_Et38mA==
인터파크_상품qna등록 인증키 = gAAAAABmRrpwomEeVDrsgzi7afYKMZg0-B3eS3eZJrZGMTQ_FOebl-Uq2KkY6XByMAtr0hbGX0_ZiOgcIVSrEOf-9q7_Et38mA==
인터파크_상품qna등록 비밀키 = gAAAAABmRrpwomEeVDrsgzi7afYKMZg0-B3eS3eZJrZGMTQ_FOebl-Uq2KkY6XByMAtr0hbGX0_ZiOgcIVSrEOf-9q7_Et38mA==
인터파크_상품qna조회 인증키 = gAAAAABmRrpwomEeVDrsgzi7afYKMZg0-B3eS3eZJrZGMTQ_FOebl-Uq2KkY6XByMAtr0hbGX0_ZiOgcIVSrEOf-9q7_Et38mA==
인터파크_상품qna조회 비밀키 = gAAAAABmRrpwomEeVDrsgzi7afYKMZg0-B3eS3eZJrZGMTQ_FOebl-Uq2KkY6XByMAtr0hbGX0_ZiOgcIVSrEOf-9q7_Et38mA==
인터파크_인터파크 업체번호 = gAAAAABmRrpwomEeVDrsgzi7afYKMZg0-B3eS3eZJrZGMTQ_FOebl-Uq2KkY6XByMAtr0hbGX0_ZiOgcIVSrEOf-9q7_Et38mA==
인터파크_공급계약 일련번호 = gAAAAABmRrpwomEeVDrsgzi7afYKMZg0-B3eS3eZJrZGMTQ_FOebl-Uq2KkY6XByMAtr0hbGX0_ZiOgcIVSrEOf-9q7_Et38mA==
위메프_api key = gAAAAABmRrpwomEeVDrsgzi7afYKMZg0-B3eS3eZJrZGMTQ_FOebl-Uq2KkY6XByMAtr0hbGX0_ZiOgcIVSrEOf-9q7_Et38mA==
옥션1.0_api key = gAAAAABmRrpwomEeVDrsgzi7afYKMZg0-B3eS3eZJrZGMTQ_FOebl-Uq2KkY6XByMAtr0hbGX0_ZiOgcIVSrEOf-9q7_Et38mA==
옥션1.0_멤버 id = gAAAAABmRrpwomEeVDrsgzi7afYKMZg0-B3eS3eZJrZGMTQ_FOebl-Uq2KkY6XByMAtr0hbGX0_ZiOgcIVSrEOf-9q7_Et38mA==
alias = 설정사업자없음
register_number = 000-00-00000
name = 설정사업자없음
date = 0000-00-00
call = 000-000-0000

1
key.key Normal file
View File

@ -0,0 +1 @@
BO25ih3w0e_UBEfR2x2NCN3fTYyw0lUjaSN5CNmjeWw=

30
main.py Normal file
View File

@ -0,0 +1,30 @@
import sys
from PyQt5.QtWidgets import QApplication, QMainWindow, QDialog
from asyncqt import QEventLoop
from ui.main_window import MainWindow
from ui.license_dialog import LicenseDialog
from utils.config import ConfigManager
from utils.logger import setup_logger
import asyncio
def main():
config = ConfigManager()
log_level = config.get('DEFAULT', 'log_level', fallback='DEBUG')
logger = setup_logger(log_level)
app = QApplication(sys.argv)
loop = QEventLoop(app)
asyncio.set_event_loop(loop)
license_dialog = LicenseDialog()
if license_dialog.exec_() == QDialog.Accepted:
main_window = MainWindow(config, logger)
main_window.show()
with loop:
loop.run_forever()
else:
sys.exit(0)
if __name__ == '__main__':
main()

351
main2.py Normal file
View File

@ -0,0 +1,351 @@
# main.py
import sys
from PyQt5.QtWidgets import (QApplication, QMainWindow, QVBoxLayout, QHBoxLayout, QPushButton, QTextBrowser, QLineEdit, QLabel, QCheckBox,
QComboBox, QProgressBar, QWidget, QMessageBox, QTabWidget)
from PyQt5.QtCore import Qt, QThread, pyqtSignal
from playwright.async_api import async_playwright
import configparser
import logging
import json
from cryptography.fernet import Fernet
import asyncio
# 설정 로드 및 저장
def load_config():
config = configparser.ConfigParser()
config.read('config.ini')
return config
def save_config(config):
with open('config.ini', 'w') as configfile:
config.write(configfile)
# 암호화 키 생성 및 로드
def generate_key():
return Fernet.generate_key()
def load_key():
try:
with open("secret.key", "rb") as key_file:
return key_file.read()
except FileNotFoundError:
key = generate_key()
with open("secret.key", "wb") as key_file:
key_file.write(key)
return key
# 암호화 및 복호화 함수
def encrypt_data(data, key):
fernet = Fernet(key)
return fernet.encrypt(data.encode())
def decrypt_data(data, key):
fernet = Fernet(key)
return fernet.decrypt(data).decode()
# 로그 설정
def setup_logging():
logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s')
logging.info("Logging setup complete.")
class LicenseAgreement(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.setWindowTitle('License Agreement')
layout = QVBoxLayout()
self.licenseText = QTextBrowser()
self.licenseText.setPlainText("License Agreement Text Here...")
layout.addWidget(self.licenseText)
self.acceptCheckbox = QCheckBox("I accept the terms and conditions.")
self.acceptCheckbox.stateChanged.connect(self.toggleAcceptButton)
layout.addWidget(self.acceptCheckbox)
self.acceptButton = QPushButton("Accept")
self.acceptButton.setEnabled(False)
self.acceptButton.clicked.connect(self.accept)
layout.addWidget(self.acceptButton)
self.cancelButton = QPushButton("Cancel")
self.cancelButton.clicked.connect(self.cancel)
layout.addWidget(self.cancelButton)
self.setLayout(layout)
def toggleAcceptButton(self, state):
self.acceptButton.setEnabled(state == Qt.Checked)
def accept(self):
self.accepted = True
self.close()
def cancel(self):
self.accepted = False
self.close()
class FetchSettingsThread(QThread):
result_ready = pyqtSignal(dict)
def run(self):
asyncio.run(self.fetch_market_settings())
async def fetch_market_settings(self):
async with async_playwright() as p:
browser = await p.chromium.launch(headless=False)
page = await browser.new_page()
await page.goto("https://percenty.co.kr")
await page.click(".signList > .ant-btn-default > span")
await page.fill(".ant-input:nth-child(4)", "your_username")
await page.fill(".ant-input:nth-child(1)", "your_password")
await page.click(".ant-btn-primary")
# 팝업 다이얼로그 닫기
try:
await page.click('xpath=body > div:nth-child(10) > div > div.ant-modal-wrap.ant-modal-centered > div > div.ant-modal-content > div.ant-modal-footer > button.ant-btn.css-1li46mu.ant-btn-primary')
except:
pass
await page.click('xpath=/html/body/div[1]/div/div/div/div/aside/div/ul/li[7]/ul/li[2]')
market_data = {}
# 각 마켓의 API key를 가져오는 로직
markets = {
"쿠팡": "/html/body/div[1]/div/div/div/div/main/div[2]/div/div[1]/div[1]/div/div[1]",
"스마트스토어": "/html/body/div[1]/div/div/div/div/main/div[2]/div/div[1]/div[1]/div/div[2]",
"옥션지마켓": "/html/body/div[1]/div/div/div/div/main/div[2]/div/div[1]/div[1]/div/div[3]",
"11번가-일반": "/html/body/div[1]/div/div/div/div/main/div[2]/div/div[1]/div[1]/div/div[4]",
"11번가-글로벌": "/html/body/div[1]/div/div/div/div/main/div[2]/div/div[1]/div[1]/div/div[5]",
"롯데온": "/html/body/div[1]/div/div/div/div/main/div[2]/div/div[1]/div[1]/div/div[6]",
}
for market, xpath in markets.items():
await page.click(f'xpath={xpath}')
if market == "쿠팡":
market_data[market] = {
"쿠팡ID": await page.get_attribute('xpath=/html/body/div[1]/div/div/div/div/main/div[2]/div/div[2]/div/div/div/div[1]/div/div[2]/div/div[2]/div[1]/input', 'value'),
"업체코드": await page.get_attribute('xpath=/html/body/div[1]/div/div/div/div/main/div[2]/div/div[2]/div/div/div/div[1]/div/div[2]/div/div[2]/div[2]/input', 'value'),
"Access Key": await page.get_attribute('xpath=/html/body/div[1]/div/div/div/div/main/div[2]/div/div[2]/div/div/div/div[1]/div/div[2]/div/div[2]/div[3]/input', 'value'),
"Secret Key": await page.get_attribute('xpath=/html/body/div[1]/div/div/div/div/main/div[2]/div/div[2]/div/div/div/div[1]/div/div[2]/div/div[2]/div[4]/input', 'value')
}
elif market == "스마트스토어":
market_data[market] = {
"애플리케이션 ID": await page.get_attribute('xpath=/html/body/div[1]/div/div/div/div/main/div[2]/div/div[2]/div/div[2]/div/div[1]/div/div[2]/div/div/div[2]/input', 'value'),
"애플리케이션 시크릿": await page.get_attribute('xpath=/html/body/div[1]/div/div/div/div/main/div[2]/div/div[2]/div/div[2]/div/div[1]/div/div[2]/div/div/div[3]/input', 'value')
}
elif market == "옥션지마켓":
market_data[market] = {
"옥션ID": await page.get_attribute('xpath=/html/body/div[1]/div/div/div/div/main/div[2]/div/div[2]/div/div[3]/div/div[1]/div/div[2]/div/div/div[1]/input', 'value'),
"G마켓ID": await page.get_attribute('xpath=/html/body/div[1]/div/div/div/div/main/div[2]/div/div[2]/div/div[3]/div/div[1]/div/div[2]/div/div/div[2]/input', 'value')
}
elif market == "11번가-일반":
market_data[market] = {
"API KEY": await page.get_attribute('xpath=/html/body/div[1]/div/div/div/div/main/div[2]/div/div[2]/div/div[4]/div/div[1]/div/div[2]/div/div/div[1]/input', 'value')
}
elif market == "11번가-글로벌":
market_data[market] = {
"API KEY": await page.get_attribute('xpath=/html/body/div[1]/div/div/div/div/main/div[2]/div/div[2]/div/div[5]/div/div[1]/div/div[2]/div/div/div[1]/input', 'value')
}
elif market == "롯데온":
market_data[market] = {
"API KEY": await page.get_attribute('xpath=/html/body/div[1]/div/div/div/div/main/div[2]/div/div[2]/div/div[6]/div/div[1]/div/div[2]/div/div/div[1]/input', 'value')
}
await browser.close()
self.result_ready.emit(market_data)
class ChangeBusinessThread(QThread):
progress_update = pyqtSignal(int)
def __init__(self, market_data):
super().__init__()
self.market_data = market_data
def run(self):
asyncio.run(self.change_business())
async def change_business(self):
async with async_playwright() as p:
browser = await p.chromium.launch(headless=False)
page = await browser.new_page()
await page.goto("https://percenty.co.kr")
await page.click(".signList > .ant-btn-default > span")
await page.fill(".ant-input:nth-child(4)", "your_username")
await page.fill(".ant-input:nth-child(1)", "your_password")
await page.click(".ant-btn-primary")
# 팝업 다이얼로그 닫기
try:
await page.click('xpath=body > div:nth-child(10) > div > div.ant-modal-wrap.ant-modal-centered > div > div.ant-modal-content > div.ant-modal-footer > button.ant-btn.css-1li46mu.ant-btn-primary')
except:
pass
await page.click('xpath=/html/body/div[1]/div/div/div/div/aside/div/ul/li[7]/ul/li[2]')
markets = self.market_data.keys()
progress_step = 100 // len(markets)
progress = 0
for market in markets:
market_xpath = {
"쿠팡": "/html/body/div[1]/div/div/div/div/main/div[2]/div/div[1]/div[1]/div/div[1]",
"스마트스토어": "/html/body/div[1]/div/div/div/div/main/div[2]/div/div[1]/div[1]/div/div[2]",
"옥션지마켓": "/html/body/div[1]/div/div/div/div/main/div[2]/div/div[1]/div[1]/div/div[3]",
"11번가-일반": "/html/body/div[1]/div/div/div/div/main/div[2]/div/div[1]/div[1]/div/div[4]",
"11번가-글로벌": "/html/body/div[1]/div/div/div/div/main/div[2]/div/div[1]/div[1]/div/div[5]",
"롯데온": "/html/body/div[1]/div/div/div/div/main/div[2]/div/div[1]/div[1]/div/div[6]"
}[market]
await page.click(f'xpath={market_xpath}')
data = self.market_data[market]
if market == "쿠팡":
await page.fill('xpath=/html/body/div[1]/div/div/div/div/main/div[2]/div/div[2]/div/div/div/div[1]/div/div[2]/div/div[2]/div[1]/input', data["쿠팡ID"])
await page.fill('xpath=/html/body/div[1]/div/div/div/div/main/div[2]/div/div[2]/div/div/div/div[1]/div/div[2]/div/div[2]/div[2]/input', data["업체코드"])
await page.fill('xpath=/html/body/div[1]/div/div/div/div/main/div[2]/div/div[2]/div/div/div/div[1]/div/div[2]/div/div[2]/div[3]/input', data["Access Key"])
await page.fill('xpath=/html/body/div[1]/div/div/div/div/main/div[2]/div/div[2]/div/div/div/div[1]/div/div[2]/div/div[2]/div[4]/input', data["Secret Key"])
elif market == "스마트스토어":
await page.fill('xpath=/html/body/div[1]/div/div/div/div/main/div[2]/div/div[2]/div/div[2]/div/div[1]/div/div[2]/div/div/div[2]/input', data["애플리케이션 ID"])
await page.fill('xpath=/html/body/div[1]/div/div/div/div/main/div[2]/div/div[2]/div/div[2]/div/div[1]/div/div[2]/div/div/div[3]/input', data["애플리케이션 시크릿"])
elif market == "옥션지마켓":
await page.fill('xpath=/html/body/div[1]/div/div/div/div/main/div[2]/div/div[2]/div/div[3]/div/div[1]/div/div[2]/div/div/div[1]/input', data["옥션ID"])
await page.fill('xpath=/html/body/div[1]/div/div/div/div/main/div[2]/div/div[2]/div/div[3]/div/div[1]/div/div[2]/div/div/div[2]/input', data["G마켓ID"])
elif market == "11번가-일반":
await page.fill('xpath=/html/body/div[1]/div/div/div/div/main/div[2]/div/div[2]/div/div[4]/div/div[1]/div/div[2]/div/div/div[1]/input', data["API KEY"])
elif market == "11번가-글로벌":
await page.fill('xpath=/html/body/div[1]/div/div/div/div/main/div[2]/div/div[2]/div/div[5]/div/div[1]/div/div[2]/div/div/div[1]/input', data["API KEY"])
elif market == "롯데온":
await page.fill('xpath=/html/body/div[1]/div/div/div/div/main/div[2]/div/div[2]/div/div[6]/div/div[1]/div/div[2]/div/div/div[1]/input', data["API KEY"])
progress += progress_step
self.progress_update.emit(progress)
await browser.close()
self.progress_update.emit(100)
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.initUI()
self.config = load_config()
self.key = load_key()
self.fetch_thread = FetchSettingsThread()
self.fetch_thread.result_ready.connect(self.updateStatus)
self.load_business_data()
def initUI(self):
self.setWindowTitle('Percenty API Manager')
mainLayout = QVBoxLayout()
self.settingButtonLayout = QHBoxLayout()
self.currentSettingButton = QPushButton("현재 설정 가져오기")
self.saveSettingButton = QPushButton("현재 설정 저장하기")
self.currentSettingButton.clicked.connect(self.fetch_current_settings)
self.saveSettingButton.clicked.connect(self.save_current_settings)
self.settingButtonLayout.addWidget(self.currentSettingButton)
self.settingButtonLayout.addWidget(self.saveSettingButton)
mainLayout.addLayout(self.settingButtonLayout)
self.currentStatusLayout = QHBoxLayout()
self.statusBox1 = QLabel("사업자 현황")
self.statusBox2 = QLabel("마켓 현황")
self.statusBox3 = QLabel("빈 박스")
self.currentStatusLayout.addWidget(self.statusBox1)
self.currentStatusLayout.addWidget(self.statusBox2)
self.currentStatusLayout.addWidget(self.statusBox3)
mainLayout.addLayout(self.currentStatusLayout)
self.selectSettingLayout = QVBoxLayout()
self.businessDropdown = QComboBox()
self.businessDropdown.currentIndexChanged.connect(self.update_market_checkboxes)
self.marketCheckboxLayout = QVBoxLayout()
self.changeBusinessButton = QPushButton("사업자 바꾸기")
self.changeBusinessButton.clicked.connect(self.change_business)
self.progressBar = QProgressBar()
self.selectSettingLayout.addWidget(self.businessDropdown)
self.selectSettingLayout.addLayout(self.marketCheckboxLayout)
self.selectSettingLayout.addWidget(self.changeBusinessButton)
self.selectSettingLayout.addWidget(self.progressBar)
mainLayout.addLayout(self.selectSettingLayout)
widget = QWidget()
widget.setLayout(mainLayout)
self.setCentralWidget(widget)
def load_business_data(self):
try:
loaded_data = self.config['BUSINESS_DATA']['data']
decrypted_data = decrypt_data(loaded_data, self.key)
self.business_data = json.loads(decrypted_data)
self.update_business_dropdown()
except KeyError:
self.business_data = {}
def update_business_dropdown(self):
self.businessDropdown.clear()
for business_name in self.business_data.keys():
self.businessDropdown.addItem(business_name)
self.update_market_checkboxes()
def fetch_current_settings(self):
self.fetch_thread.start()
def save_current_settings(self):
encrypted_data = encrypt_data(json.dumps(self.business_data), self.key)
self.config['BUSINESS_DATA'] = {'data': encrypted_data}
save_config(self.config)
QMessageBox.information(self, "Success", "Current settings have been saved.")
def updateStatus(self, market_data):
business_name = self.businessDropdown.currentText()
if business_name:
self.business_data[business_name]["markets"] = market_data
self.update_market_checkboxes()
self.statusBox1.setText(f"사업자 현황: {business_name}")
self.statusBox2.setText(json.dumps(market_data, indent=4, ensure_ascii=False))
def update_market_checkboxes(self):
business_name = self.businessDropdown.currentText()
if not business_name:
return
self.clear_layout(self.marketCheckboxLayout)
markets = self.business_data[business_name]["markets"]
for market, details in markets.items():
market_checkbox = QCheckBox(market)
market_checkbox.setChecked(details["api_key"] != "")
self.marketCheckboxLayout.addWidget(market_checkbox)
def clear_layout(self, layout):
while layout.count():
child = layout.takeAt(0)
if child.widget():
child.widget().deleteLater()
def change_business(self):
business_name = self.businessDropdown.currentText()
selected_markets = [checkbox.text() for checkbox in self.findChildren(QCheckBox) if checkbox.isChecked()]
if business_name:
market_data = {market: self.business_data[business_name]["markets"][market] for market in selected_markets}
self.change_thread = ChangeBusinessThread(market_data)
self.change_thread.progress_update.connect(self.update_progress)
self.change_thread.start()
def update_progress(self, value):
self.progressBar.setValue(value)
if __name__ == "__main__":
setup_logging()
app = QApplication(sys.argv)
licenseWindow = LicenseAgreement()
licenseWindow.show()
app.exec_()
if licenseWindow.accepted:
mainWindow = MainWindow()
mainWindow.show()
sys.exit(app.exec_())

0
requirements.txt Normal file
View File

1
secret.key Normal file
View File

@ -0,0 +1 @@
-RX8kOGCLzoZz9xxvqB4mh_VULiqV7KLMbdokG7npes=

0
ui/__init__.py Normal file
View File

102
ui/business_settings.py Normal file
View File

@ -0,0 +1,102 @@
from PyQt5.QtWidgets import QDialog, QVBoxLayout, QTabWidget, QWidget, QFormLayout, QLineEdit, QPushButton, QHBoxLayout, QLabel
from utils.config import ConfigManager
class BusinessSettingsDialog(QDialog):
def __init__(self, config: ConfigManager):
super().__init__()
self.config = config
self.setWindowTitle('사업자 설정')
self.init_ui()
def init_ui(self):
layout = QVBoxLayout()
self.tab_widget = QTabWidget()
business_count = int(self.config.get('DEFAULT', 'business_count', fallback='0'))
for i in range(business_count):
self.add_business_tab(i, load=True)
layout.addWidget(self.tab_widget)
button_layout = QHBoxLayout()
add_button = QPushButton('사업자 추가')
add_button.clicked.connect(self.add_new_business_tab)
save_button = QPushButton('저장')
save_button.clicked.connect(self.save_settings)
cancel_button = QPushButton('취소')
cancel_button.clicked.connect(self.reject)
button_layout.addWidget(add_button)
button_layout.addWidget(save_button)
button_layout.addWidget(cancel_button)
layout.addLayout(button_layout)
self.setLayout(layout)
def add_business_tab(self, index, load=False):
tab = QWidget()
form_layout = QFormLayout()
tab.setLayout(form_layout)
alias = QLineEdit(self)
business_number = QLineEdit(self)
business_name = QLineEdit(self)
registration_date = QLineEdit(self)
contact_number = QLineEdit(self)
if load:
alias.setText(self.config.get(f'BUSINESS_{index}', 'alias', fallback=''))
business_number.setText(self.config.get(f'BUSINESS_{index}', 'business_number', fallback=''))
business_name.setText(self.config.get(f'BUSINESS_{index}', 'business_name', fallback=''))
registration_date.setText(self.config.get(f'BUSINESS_{index}', 'registration_date', fallback=''))
contact_number.setText(self.config.get(f'BUSINESS_{index}', 'contact_number', fallback=''))
form_layout.addRow('사업자 별칭:', alias)
form_layout.addRow('사업자 등록번호:', business_number)
form_layout.addRow('상호명:', business_name)
form_layout.addRow('등록 날짜:', registration_date)
form_layout.addRow('응대 전화번호:', contact_number)
self.tab_widget.addTab(tab, f'사업자 {index + 1}')
def add_new_business_tab(self):
business_count = self.tab_widget.count()
max_businesses = int(self.config.get('DEFAULT', 'max_businesses', fallback='5'))
if business_count >= max_businesses:
self.show_error_message(f'최대 {max_businesses}개의 사업자만 추가할 수 있습니다.')
return
self.add_business_tab(business_count)
def show_error_message(self, message):
error_dialog = QDialog(self)
error_dialog.setWindowTitle('에러')
error_layout = QVBoxLayout()
error_label = QLabel(message)
error_layout.addWidget(error_label)
error_button = QPushButton('확인')
error_button.clicked.connect(error_dialog.accept)
error_layout.addWidget(error_button)
error_dialog.setLayout(error_layout)
error_dialog.exec_()
def save_settings(self):
business_count = self.tab_widget.count()
self.config.set('DEFAULT', 'business_count', str(business_count))
for i in range(business_count):
tab = self.tab_widget.widget(i)
form_layout = tab.layout()
alias = form_layout.itemAt(0, QFormLayout.FieldRole).widget().text()
business_number = form_layout.itemAt(1, QFormLayout.FieldRole).widget().text()
business_name = form_layout.itemAt(2, QFormLayout.FieldRole).widget().text()
registration_date = form_layout.itemAt(3, QFormLayout.FieldRole).widget().text()
contact_number = form_layout.itemAt(4, QFormLayout.FieldRole).widget().text()
self.config.set(f'BUSINESS_{i}', 'alias', alias)
self.config.set(f'BUSINESS_{i}', 'business_number', business_number)
self.config.set(f'BUSINESS_{i}', 'business_name', business_name)
self.config.set(f'BUSINESS_{i}', 'registration_date', registration_date)
self.config.set(f'BUSINESS_{i}', 'contact_number', contact_number)
self.accept()

22
ui/help_dialog.py Normal file
View File

@ -0,0 +1,22 @@
from PyQt5.QtWidgets import QDialog, QVBoxLayout, QTextBrowser, QPushButton, QHBoxLayout
class HelpDialog(QDialog):
def __init__(self):
super().__init__()
self.setWindowTitle('도움말')
self.init_ui()
def init_ui(self):
layout = QVBoxLayout()
help_text = QTextBrowser()
help_text.setPlainText('도움말 내용을 여기에 작성합니다.')
layout.addWidget(help_text)
button_layout = QHBoxLayout()
close_button = QPushButton('닫기')
close_button.clicked.connect(self.accept)
button_layout.addWidget(close_button)
layout.addLayout(button_layout)
self.setLayout(layout)

32
ui/license_dialog.py Normal file
View File

@ -0,0 +1,32 @@
from PyQt5.QtWidgets import QDialog, QVBoxLayout, QLabel, QCheckBox, QPushButton, QHBoxLayout
class LicenseDialog(QDialog):
def __init__(self):
super().__init__()
self.setWindowTitle('라이센스 동의')
self.init_ui()
def init_ui(self):
layout = QVBoxLayout()
license_text = QLabel('라이센스 동의 내용을 여기에 작성합니다.')
layout.addWidget(license_text)
self.agree_checkbox = QCheckBox('동의합니다.')
self.agree_checkbox.stateChanged.connect(self.toggle_accept_button)
layout.addWidget(self.agree_checkbox)
button_layout = QHBoxLayout()
self.accept_button = QPushButton('Accept')
self.accept_button.setEnabled(False)
self.accept_button.clicked.connect(self.accept)
cancel_button = QPushButton('Cancel')
cancel_button.clicked.connect(self.reject)
button_layout.addWidget(self.accept_button)
button_layout.addWidget(cancel_button)
layout.addLayout(button_layout)
self.setLayout(layout)
def toggle_accept_button(self):
self.accept_button.setEnabled(self.agree_checkbox.isChecked())

509
ui/main_window.py Normal file
View File

@ -0,0 +1,509 @@
from PyQt5.QtWidgets import (QMainWindow, QAction, QVBoxLayout, QHBoxLayout, QWidget, QPushButton, QLabel, QProgressBar, QComboBox, QCheckBox, QTextBrowser, QPlainTextEdit, QDialog, QFrame, QLineEdit,QGridLayout)
from PyQt5.QtCore import Qt
from ui.percenty_settings import PercentySettingsDialog
from ui.business_settings import BusinessSettingsDialog
from ui.help_dialog import HelpDialog
from utils.playwright_helpers import PlaywrightHelper
from utils.config import ConfigManager
import asyncio
class MainWindow(QMainWindow):
def __init__(self, config, logger):
super().__init__()
self.config = config
self.logger = logger
self.playwright_helper = PlaywrightHelper()
self.setWindowTitle('Change-Percenty2')
self.setGeometry(100, 100, 450, 800)
self.init_ui()
def init_ui(self):
main_layout = QVBoxLayout()
# 상단의 도움말, 퍼센티 설정, 사업자 설정 메뉴
self.create_menu()
# 메인 레이아웃 설정
main_layout.addLayout(self.create_main_layout())
# 상태 라벨 추가
self.status_label = QLabel('현재 상태: 준비 완료')
main_layout.addWidget(self.status_label)
container = QWidget()
container.setLayout(main_layout)
self.setCentralWidget(container)
def create_menu(self):
menubar = self.menuBar()
# 도움말 메뉴
help_menu = menubar.addMenu('도움말')
help_action = QAction('도움말 보기', self)
help_action.triggered.connect(self.show_help)
help_menu.addAction(help_action)
# 퍼센티 설정 메뉴
percenty_menu = menubar.addMenu('퍼센티 설정')
percenty_action = QAction('퍼센티 설정', self)
percenty_action.triggered.connect(self.show_percenty_settings)
percenty_menu.addAction(percenty_action)
# 사업자 설정 메뉴
business_menu = menubar.addMenu('사업자 설정')
business_action = QAction('사업자 설정', self)
business_action.triggered.connect(self.show_business_settings)
business_menu.addAction(business_action)
def create_main_layout(self):
layout = QVBoxLayout()
# self.top_frame = QFrame(self)
# self.top_frame.setFrameShape(QFrame.StyledPanel)
# self.top_frame.setFrameShadow(QFrame.Raised)
# self.top_layout = QHBoxLayout(self.top_frame)
# self.middle_frame = QFrame(self)
# self.middle_frame.setFrameShape(QFrame.StyledPanel)
# self.middle_frame.setFrameShadow(QFrame.Raised)
# self.middle_layout = QHBoxLayout(self.middle_frame)
# self.bottom_frame = QFrame(self)
# self.bottom_frame.setFrameShape(QFrame.StyledPanel)
# self.bottom_frame.setFrameShadow(QFrame.Raised)
# self.bottom_layout = QVBoxLayout(self.bottom_frame)
top_layout = QHBoxLayout()
middle_layout = QVBoxLayout()
bottom_layout = QVBoxLayout()
# 상단 레이아웃
self.create_top_layout(top_layout)
# 중단 레이아웃
self.create_middle_layout(middle_layout)
# 하단 레이아웃
self.create_bottom_layout(bottom_layout)
# QFrame으로 감싸고 테두리 설정
top_frame = QFrame()
top_frame.setLayout(top_layout)
top_frame.setFrameShape(QFrame.Box)
top_frame.setFrameShadow(QFrame.Raised)
middle_frame = QFrame()
middle_frame.setLayout(middle_layout)
middle_frame.setFrameShape(QFrame.Box)
middle_frame.setFrameShadow(QFrame.Raised)
bottom_frame = QFrame()
bottom_frame.setLayout(bottom_layout)
bottom_frame.setFrameShape(QFrame.Box)
bottom_frame.setFrameShadow(QFrame.Raised)
layout.addWidget(top_frame, 10)
layout.addWidget(middle_frame, 60)
layout.addWidget(bottom_frame, 30)
return layout
def create_top_layout(self, layout):
self.fetch_button = QPushButton('현재설정 가져오기')
self.fetch_button.setMinimumSize(150,50)
self.fetch_button.clicked.connect(lambda: asyncio.ensure_future(self.fetch_settings()))
layout.addWidget(self.fetch_button)
self.save_button = QPushButton('현재설정 저장하기')
self.save_button.setMinimumSize(150,50)
self.save_button.clicked.connect(lambda: asyncio.ensure_future(self.save_settings()))
layout.addWidget(self.save_button)
def create_middle_layout(self, layout):
# currentStatusLayout 추가
current_status_layout = QVBoxLayout()
# 첫 번째 박스 (사업자 현황)
self.business_info_box = QGridLayout()
self.business_info_label = QLabel('현재 사업자 정보(별칭)')
self.business_info_label_context = QLineEdit('------')
self.business_register_number_label = QLabel('사업자등록번호')
self.business_register_number_label_context = QLineEdit('------')
self.business_name_label = QLabel('상호명')
self.business_name_label_context = QLineEdit('------')
self.business_date_label = QLabel('등록날짜')
self.business_date_label_context = QLineEdit('------')
self.business_call_label = QLabel('전화번호')
self.business_call_label_context = QLineEdit('------')
self.business_info_box.addWidget(self.business_info_label,1,1,1,2)
self.business_info_box.addWidget(self.business_info_label_context,1,3,1,2)
self.business_info_box.addWidget(self.business_register_number_label,2,1)
self.business_info_box.addWidget(self.business_register_number_label_context,3,1)
self.business_info_box.addWidget(self.business_name_label,2,2)
self.business_info_box.addWidget(self.business_name_label_context,3,2)
self.business_info_box.addWidget(self.business_date_label,2,3)
self.business_info_box.addWidget(self.business_date_label_context,3,3)
self.business_info_box.addWidget(self.business_call_label,2,4)
self.business_info_box.addWidget(self.business_call_label_context,3,4)
self.business_info_box.setContentsMargins(10,10,10,10)
self.business_info_box.setSpacing(10)
business_frame = QFrame()
business_frame.setLayout(self.business_info_box)
self.business_call_label.setStyleSheet
business_frame.setFrameShape(QFrame.Box)
# business_frame.setFrameShadow(QFrame.Plain)
# business_frame.setStyleSheet("border: 1px dashed black;")
current_status_layout.addWidget(business_frame, 30)
# 두 번째 박스 (마켓 현황)
self.market_info_box = QGridLayout()
self.market_info_label = QLabel('마켓 정보')
self.market_info_cc_btn = QPushButton('쿠팡')
self.market_info_cc_label = QLabel('------')
self.market_info_ss_btn = QPushButton('스스')
self.market_info_ss_label = QLabel('------')
self.market_info_dm11_btn = QPushButton('11국내')
self.market_info_dm11_label = QLabel('------')
self.market_info_gb11_btn = QPushButton('11해외')
self.market_info_gb11_label = QLabel('------')
self.market_info_esm_btn = QPushButton('ESM')
self.market_info_esm_label = QLabel('------')
self.market_info_lton_btn = QPushButton('롯데온')
self.market_info_lton_label = QLabel('------')
self.market_info_ip_btn = QPushButton('인터파크')
self.market_info_ip_label = QLabel('------')
self.market_info_wmp_btn = QPushButton('위메프')
self.market_info_wmp_label = QLabel('------')
self.market_info_at_btn = QPushButton('옥션1.0')
self.market_info_at_label = QLabel('------')
# self.market_info_cc_btn.clicked.connect(self.market_info_cc_btn_clicked)
# self.market_info_ss_btn.clicked.connect(self.market_info_cc_btn_clicked)
# self.market_info_dm11_btn.clicked.connect(self.market_info_cc_btn_clicked)
# self.market_info_gb11_btn.clicked.connect(self.market_info_cc_btn_clicked)
# self.market_info_esm_btn.clicked.connect(self.market_info_cc_btn_clicked)
# self.market_info_lton_btn.clicked.connect(self.market_info_cc_btn_clicked)
# self.market_info_ip_btn.clicked.connect(self.market_info_cc_btn_clicked)
# self.market_info_wmp_btn.clicked.connect(self.market_info_cc_btn_clicked)
# self.market_info_at_btn.clicked.connect(self.market_info_cc_btn_clicked)
# def market_info_cc_btn_clicked(self)
# pass
self.market_info_box.addWidget(self.market_info_label,1,1,1,2)
self.market_info_box.addWidget(self.market_info_cc_btn,2,1)
self.market_info_box.addWidget(self.market_info_cc_label,2,2)
self.market_info_box.addWidget(self.market_info_ss_btn,2,3)
self.market_info_box.addWidget(self.market_info_ss_label,2,4)
self.market_info_box.addWidget(self.market_info_dm11_btn,3,1)
self.market_info_box.addWidget(self.market_info_dm11_label,3,2)
self.market_info_box.addWidget(self.market_info_gb11_btn,3,3)
self.market_info_box.addWidget(self.market_info_gb11_label,3,4)
self.market_info_box.addWidget(self.market_info_esm_btn,4,1)
self.market_info_box.addWidget(self.market_info_esm_label,4,2)
self.market_info_box.addWidget(self.market_info_lton_btn,4,3)
self.market_info_box.addWidget(self.market_info_lton_label,4,4)
self.market_info_box.addWidget(self.market_info_ip_btn,5,1)
self.market_info_box.addWidget(self.market_info_ip_label,5,2)
self.market_info_box.addWidget(self.market_info_wmp_btn,5,3)
self.market_info_box.addWidget(self.market_info_wmp_label,5,4)
self.market_info_box.addWidget(self.market_info_at_btn,6,1)
self.market_info_box.addWidget(self.market_info_at_label,6,2)
market_frame = QFrame()
market_frame.setLayout(self.market_info_box)
market_frame.setFrameShape(QFrame.Box)
current_status_layout.addWidget(market_frame, 40)
# 세 번째 박스 (비어 있음)
self.empty_box = QVBoxLayout()
empty_frame = QFrame()
empty_frame.setLayout(self.empty_box)
empty_frame.setFrameShape(QFrame.Box)
empty_frame.setFrameShadow(QFrame.Plain)
empty_frame.setStyleSheet("border: 1px dashed black;")
current_status_layout.addWidget(empty_frame, 30)
layout.addLayout(current_status_layout)
def create_bottom_layout(self, layout):
self.business_dropdown = QComboBox()
layout.addWidget(self.business_dropdown)
self.market_checkbox_layout = QGridLayout()
layout.addLayout(self.market_checkbox_layout)
# 체크박스만 추가
self.all_checkbox = QCheckBox("전체 체크")
self.cp_checkbox = QCheckBox("쿠팡")
self.ss_checkbox = QCheckBox("스스")
self.st11_dm_checkbox = QCheckBox("11번가-국내")
self.st11_gb_checkbox = QCheckBox("11번가-해외")
self.esm_checkbox = QCheckBox("ESM")
self.lton_checkbox = QCheckBox("롯데온")
self.ip_checkbox = QCheckBox("인터파크")
self.wmp_checkbox = QCheckBox("위메프")
self.at_checkbox = QCheckBox("옥션1.0")
self.all_checkbox.stateChanged.connect(self.handle_all_checked)
self.market_checkbox_layout.addWidget(self.all_checkbox,1,1)
self.market_checkbox_layout.addWidget(self.cp_checkbox,2,1)
self.market_checkbox_layout.addWidget(self.ss_checkbox,2,2)
self.market_checkbox_layout.addWidget(self.st11_dm_checkbox,2,3)
self.market_checkbox_layout.addWidget(self.st11_gb_checkbox,3,1)
self.market_checkbox_layout.addWidget(self.esm_checkbox,3,2)
self.market_checkbox_layout.addWidget(self.lton_checkbox,3,3)
self.market_checkbox_layout.addWidget(self.ip_checkbox,4,1)
self.market_checkbox_layout.addWidget(self.wmp_checkbox,4,2)
self.market_checkbox_layout.addWidget(self.at_checkbox,4,3)
self.change_business_button = QPushButton('사업자 바꾸기')
self.change_business_button.clicked.connect(lambda: asyncio.ensure_future(self.change_business()))
layout.addWidget(self.change_business_button)
self.progress_bar = QProgressBar(self)
self.progress_bar.setAlignment(Qt.AlignCenter)
layout.addWidget(self.progress_bar)
def handle_all_checked(self, state):
if state == Qt.Checked:
self.cp_checkbox.setChecked(True)
self.ss_checkbox.setChecked(True)
self.st11_dm_checkbox.setChecked(True)
self.st11_gb_checkbox.setChecked(True)
self.esm_checkbox.setChecked(True)
self.lton_checkbox.setChecked(True)
self.ip_checkbox.setChecked(True)
self.wmp_checkbox.setChecked(True)
self.at_checkbox.setChecked(True)
elif state == Qt.Unchecked:
self.cp_checkbox.setChecked(False)
self.ss_checkbox.setChecked(False)
self.st11_dm_checkbox.setChecked(False)
self.st11_gb_checkbox.setChecked(False)
self.esm_checkbox.setChecked(False)
self.lton_checkbox.setChecked(False)
self.ip_checkbox.setChecked(False)
self.wmp_checkbox.setChecked(False)
self.at_checkbox.setChecked(False)
async def fetch_settings(self):
self.logger.debug("Fetching settings...")
self.status_label.setText('현재 상태: 설정 가져오는 중...')
self.progress_bar.setValue(0)
await self.playwright_helper.init_browser()
self.progress_bar.setValue(5)
user_id = self.config.get('USER', 'user_id')
password = self.config.decrypt(self.config.get('USER', 'password'))
api_keys = await self.playwright_helper.login_and_fetch_api_keys('https://percenty.co.kr', user_id, password, self.status_label, self.progress_bar)
print(f"가져온 apikeys\n{api_keys}")
business_info = self.search_apikeys(api_keys)
# 가져온 API 키를 UI에 업데이트하는 로직 추가
self.update_market_info(api_keys, business_info)
self.progress_bar.setValue(100)
self.status_label.setText('현재 상태: 설정 가져오기 완료')
await self.playwright_helper.close_browser()
def search_apikeys(self, api_keys):
self.status_label.setText('현재 상태: 키 검증하기')
business_info = {
'사업자별칭': '설정사업자없음',
'사업자등록번호': '000-00-00000',
'상호명': '설정사업자없음',
'등록날짜': '0000-00-00',
'응대전화번호': '000-000-0000'
}
# max_business = int(self.config.get('DEFAULT', 'max_businesses'))
all = self.config.get_all_businesses()
print(f"사업자 수 : {len(all)}")
print(f"all : {all}")
progress_step = 15 / len(all)
print(f"progress_step : {progress_step}")
try:
# 저장된 모든 사업자 정보 가져오기
for business_section in all:
print(f"키검증 business_section : {business_section}")
stored_api_keys = self.config.get_api_keys(business_section)
print(f"키검증 stored_api_keys : {stored_api_keys}")
if stored_api_keys and stored_api_keys == api_keys:
print("stored_api_keys 존재함")
business_info = self.config.get_business_info(business_section)
print(f"business_info : {business_info}")
break
else:
print("else")
print("progress_bar")
self.progress_bar.setValue(80 + int(progress_step))
self.status_label.setText(f'현재 상태: {business_section} 사업자 가져오기 완료')
except Exception as e:
print(f"{e}")
print(f"business_info{business_info}")
return business_info
def update_market_info(self, api_keys, business_info):
print(f"update_market_info : {api_keys}, {business_info}")
# 사업자 정보 업데이트
self.business_info_label_context.setText(business_info['사업자별칭'])
self.business_register_number_label_context.setText(business_info['사업자등록번호'])
self.business_name_label_context.setText(business_info['상호명'])
self.business_date_label_context.setText(business_info['등록날짜'])
self.business_call_label_context.setText(business_info['응대전화번호'])
# 마켓 정보 업데이트
market_buttons = [
(self.market_info_cc_btn, '쿠팡', self.market_info_cc_label),
(self.market_info_ss_btn, '스스', self.market_info_ss_label),
(self.market_info_dm11_btn, '11번가-국내', self.market_info_dm11_label),
(self.market_info_gb11_btn, '11번가-해외', self.market_info_gb11_label),
(self.market_info_esm_btn, 'ESM', self.market_info_esm_label),
(self.market_info_lton_btn, '롯데온', self.market_info_lton_label),
(self.market_info_ip_btn, '인터파크', self.market_info_ip_label),
(self.market_info_wmp_btn, '위메프', self.market_info_wmp_label),
(self.market_info_at_btn, '옥션1.0', self.market_info_at_label),
]
for button, market, label in market_buttons:
market_info = api_keys.get(market, None)
if market_info:
button.setStyleSheet("background-color: lightgreen;")
label.setText(business_info['사업자별칭'])
else:
button.setStyleSheet("background-color: darkgray;")
label.setText("NoMatch")
async def save_settings(self):
self.logger.debug("Saving settings...")
self.status_label.setText('현재 상태: 설정 저장하는 중...')
self.progress_bar.setValue(0)
# 현재 QLineEdit 값들을 가져와서 사업자 정보 업데이트
business_info = {
'사업자별칭': self.business_info_label_context.text(),
'사업자등록번호': self.business_register_number_label_context.text(),
'상호명': self.business_name_label_context.text(),
'등록날짜': self.business_date_label_context.text(),
'응대전화번호': self.business_call_label_context.text()
}
self.config.set_business_info(1, business_info)
# 예시 API 키 설정
api_keys = {
'쿠팡': {
'쿠팡ID': 'example_coupang_id',
'업체 코드': 'example_company_code',
'Access Key': 'example_access_key',
'Secret Key': 'example_secret_key'
},
'스마트스토어': {
'애플리케이션 ID': 'example_application_id',
'애플리케이션 시크릿': 'example_application_secret'
},
'옥션지마켓': {
'옥션ID': 'example_auction_id',
'G마켓 ID': 'example_gmarket_id'
},
'11번가-일반': {
'API KEY': 'example_11st_api_key'
},
'11번가-글로벌': {
'API KEY': 'example_11st_global_api_key'
},
'롯데온': {
'API KEY': 'example_lotteon_api_key'
},
}
self.config.set_api_keys(1, api_keys)
self.progress_bar.setValue(100)
self.status_label.setText('현재 상태: 설정 저장 완료')
await self.playwright_helper.close_browser()
async def change_business(self):
self.logger.debug("Changing business...")
self.status_label.setText('현재 상태: 사업자 변경 중...')
self.progress_bar.setValue(0)
# 사업자 드롭박스에서 선택된 사업자와 마켓 체크박스에서 선택된 마켓 가져오기
selected_business = self.business_dropdown.currentText()
selected_markets = [checkbox.text() for checkbox in self.market_checkbox_layout.children() if checkbox.isChecked()]
# 선택된 사업자와 마켓에 따라 API 키 변경 작업 수행
await self.playwright_helper.init_browser()
user_id = self.config.get('USER', 'user_id')
password = self.config.decrypt(self.config.get('USER', 'password'))
api_keys = {} # 여기에 새로운 API 키를 설정하는 로직 추가
await self.playwright_helper.update_api_keys('https://percenty.co.kr', user_id, password, api_keys, self.status_label, self.progress_bar)
self.progress_bar.setValue(100)
self.status_label.setText('현재 상태: 사업자 변경 완료')
await self.playwright_helper.close_browser()
# 작업 완료 창 띄우기
self.show_completion_dialog()
def show_completion_dialog(self):
dialog = QDialog(self)
dialog.setWindowTitle('작업 완료')
layout = QVBoxLayout()
completion_label = QLabel('사업자 변경 작업이 완료되었습니다.')
layout.addWidget(completion_label)
browser_button = QPushButton('브라우저 실행')
browser_button.clicked.connect(lambda: asyncio.ensure_future(self.run_browser()))
layout.addWidget(browser_button)
close_button = QPushButton('확인')
close_button.clicked.connect(dialog.accept)
layout.addWidget(close_button)
dialog.setLayout(layout)
dialog.exec_()
async def run_browser(self):
await self.playwright_helper.init_browser(headless=False)
user_id = self.config.get('USER', 'user_id')
password = self.config.decrypt(self.config.get('USER', 'password'))
await self.playwright_helper.login_and_fetch_api_keys('https://percenty.co.kr', user_id, password)
def show_help(self):
dialog = HelpDialog()
dialog.exec_()
def show_percenty_settings(self):
dialog = PercentySettingsDialog(self.config)
dialog.exec_()
def show_business_settings(self):
dialog = BusinessSettingsDialog(self.config)
dialog.exec_()

54
ui/percenty_settings.py Normal file
View File

@ -0,0 +1,54 @@
from PyQt5.QtWidgets import QDialog, QVBoxLayout, QLabel, QLineEdit, QPushButton, QHBoxLayout
from utils.config import ConfigManager
class PercentySettingsDialog(QDialog):
def __init__(self, config: ConfigManager):
super().__init__()
self.config = config
self.setWindowTitle('퍼센티 설정')
self.init_ui()
def init_ui(self):
layout = QVBoxLayout()
self.user_id_label = QLabel('사용자 아이디:')
self.user_id_input = QLineEdit(self)
layout.addWidget(self.user_id_label)
layout.addWidget(self.user_id_input)
self.password_label = QLabel('비밀번호:')
self.password_input = QLineEdit(self)
self.password_input.setEchoMode(QLineEdit.Password)
layout.addWidget(self.password_label)
layout.addWidget(self.password_input)
button_layout = QHBoxLayout()
save_button = QPushButton('저장')
save_button.clicked.connect(self.save_settings)
cancel_button = QPushButton('취소')
cancel_button.clicked.connect(self.reject)
button_layout.addWidget(save_button)
button_layout.addWidget(cancel_button)
layout.addLayout(button_layout)
self.setLayout(layout)
# 기존 설정 불러오기
self.load_settings()
def load_settings(self):
user_id = self.config.get('USER', 'user_id', fallback='')
encrypted_password = self.config.get('USER', 'password', fallback='')
password = self.config.decrypt(encrypted_password) if encrypted_password else ''
self.user_id_input.setText(user_id)
self.password_input.setText(password)
def save_settings(self):
user_id = self.user_id_input.text()
password = self.password_input.text()
self.config.set('USER', 'user_id', user_id)
self.config.set('USER', 'password', self.config.encrypt(password))
self.accept()

0
utils/__init__.py Normal file
View File

212
utils/config.py Normal file
View File

@ -0,0 +1,212 @@
import configparser
from cryptography.fernet import Fernet, InvalidToken
import os
class ConfigManager:
def __init__(self, config_file='config.ini'):
self.config_file = config_file
self.config = configparser.ConfigParser()
self.valid_markets = ['쿠팡', '스마트스토어','옥션지마켓', '11번가-일반','11번가-글로벌', '롯데온','인터파크', '위메프', '옥션1.0'] # 여기에 원하는 마켓 이름을 추가하세요
if not os.path.exists(config_file):
self._create_default_config()
self.config.read(config_file, encoding='utf-8')
if 'DEFAULT' not in self.config or 'encryption_key' not in self.config['DEFAULT']:
self.key = Fernet.generate_key()
self.config['DEFAULT']['encryption_key'] = self.key.decode()
with open(self.config_file, 'w') as configfile:
self.config.write(configfile)
else:
self.key = self.config['DEFAULT']['encryption_key'].encode()
self.cipher_suite = Fernet(self.key)
def _create_default_config(self):
self.config['DEFAULT'] = {
'max_businesses': '5',
'log_level': 'DEBUG',
'business_count': '0',
'encryption_key': Fernet.generate_key().decode()
}
with open(self.config_file, 'w') as configfile:
self.config.write(configfile)
def get(self, section, option, fallback=None):
return self.config.get(section, option, fallback=fallback)
def set(self, section, option, value):
if not self.config.has_section(section):
self.config.add_section(section)
self.config.set(section, option, value)
with open(self.config_file, 'w') as configfile:
self.config.write(configfile)
def encrypt(self, data):
return self.cipher_suite.encrypt(data.encode()).decode()
def decrypt(self, encrypted_data):
print(f"encrypted_data : {encrypted_data} ")
try:
print("decrypt Try")
result = self.cipher_suite.decrypt(encrypted_data.encode()).decode()
print(f"result : {result}")
return result
except InvalidToken:
raise ValueError("Invalid encryption key or corrupted data.")
def get_business_info(self, business_section):
if not self.config.has_section(business_section):
print(f"{business_section} : 해당 섹션이 없음")
return None
print(f"business_section : {business_section}")
print(f"self.config.get(business_section, '사업자별칭', fallback='설정사업자없음') \n {self.config.get(business_section, '사업자별칭', fallback='설정사업자없음')}")
business_info = {
'사업자별칭': self.config.get(business_section, '사업자별칭', fallback='설정사업자없음'),
'사업자등록번호': self.config.get(business_section, '사업자등록번호', fallback='000-00-00000'),
'상호명': self.config.get(business_section, '상호명', fallback='설정사업자없음'),
'등록날짜': self.config.get(business_section, '등록날짜', fallback='0000-00-00'),
'응대전화번호': self.config.get(business_section, '응대전화번호', fallback='000-000-0000')
}
return business_info
def set_business_info(self, business_id, business_info):
business_section = f'BUSINESS_{business_id}'
self.set(business_section, 'alias', business_info['사업자별칭'])
self.set(business_section, 'register_number', business_info['사업자등록번호'])
self.set(business_section, 'name', business_info['상호명'])
self.set(business_section, 'date', business_info['등록날짜'])
self.set(business_section, 'call', business_info['응대전화번호'])
def get_all_businesses(self):
businesses = []
for section in self.config.sections():
if section.startswith('BUSINESS_'):
businesses.append(section)
return businesses
def get_api_keys(self, business_section):
print("get_api_keys")
print(f"business_section : {business_section}")
if not self.config.has_section(business_section):
print("business_section이 존재하지 않음")
return {}
api_keys = {}
for key in self.config.options(business_section):
print(f"key : {key}")
market_name = key.split('_', 1)[0]
print(f"market_name : {market_name}")
if market_name in self.valid_markets and '_' in key:
market, key_name = key.split('_', 1)
print(f"market : {market}")
print(f"key_name : {key_name}")
if market not in api_keys:
api_keys[market] = {}
print("market not in api_keys, 마켓생성")
encrypted_value = self.config.get(business_section, key)
print(f"encrypted_value : {encrypted_value}")
if encrypted_value:
try:
decrypted_value = self.decrypt(encrypted_value)
print(f"decrypted_value : {decrypted_value}")
api_keys[market][key_name] = decrypted_value
except Exception as e:
print(f"Decryption failed for key {key}: {e}")
api_keys[market][key_name] = ''
else:
api_keys[market][key_name] = ''
print(f"Empty value for key {key}, setting as empty string")
print(f"최종 api_keys: {api_keys}")
return api_keys
def get_api_keys_2(self, business_id):
section = f'API_KEYS_{business_id}'
if not self.config.has_section(section):
return None
return {
'쿠팡': {
'쿠팡ID': self.get(section, 'coupang_coupangid', ''),
'업체 코드': self.get(section, 'coupang_업체_코드', ''),
'Access Key': self.get(section, 'coupang_access_key', ''),
'Secret Key': self.get(section, 'coupang_secret_key', '')
},
'스마트스토어': {
'업로드항 스마트스토어 계정': self.get(section, 'ss_업로드항_스마트스토어_계정', ''),
'애플리케이션 ID': self.get(section, 'ss_application_id', ''),
'애플리케이션 시크릿': self.get(section, 'ss_application_secret', '')
},
'옥션지마켓': {
'옥션ID': self.get(section, 'esm_auction_id', ''),
'G마켓 ID': self.get(section, 'esm_gmarket_id', '')
},
'11번가-일반': {
'API KEY': self.get(section, 'est_api_key', '')
},
'11번가-글로벌': {
'API KEY': self.get(section, 'est_global_api_key', '')
},
'롯데온': {
'API KEY': self.get(section, 'lotteon_api_key', '')
},
'인터파크': {
'상품상태재고수정 인증키': self.get(section, 'ip_product_status_inventory_update_auth_key', ''),
'상품상태재고수정 비밀키': self.get(section, 'ip_product_status_inventory_update_secret_key', ''),
'상품재고조회 인증키': self.get(section, 'ip_product_inventory_check_auth_key', ''),
'상품재고조회 비밀키': self.get(section, 'ip_product_inventory_check_secret_key', ''),
'상품정보조회 인증': self.get(section, 'ip_product_info_check_auth_key', ''),
'상품정보조회 비밀키': self.get(section, 'ip_product_info_check_secret_key', ''),
'상품수정 인증키': self.get(section, 'ip_product_update_auth_key', ''),
'상품수정 비밀키': self.get(section, 'ip_product_update_secret_key', ''),
'상품등록 인증키': self.get(section, 'ip_product_register_auth_key', ''),
'상품등록 비밀키': self.get(section, 'ip_product_register_secret_key', ''),
'반품배송지조회 인증키': self.get(section, 'ip_return_address_check_auth_key', ''),
'반품배송지조회 비밀키': self.get(section, 'ip_return_address_check_secret_key', ''),
'반품배송지등록 인증키': self.get(section, 'ip_return_address_register_auth_key', ''),
'반품배송지등록 비밀키': self.get(section, 'ip_return_address_register_secret_key', ''),
'상품QnA등록 인증키': self.get(section, 'ip_product_qna_register_auth_key', ''),
'상품QnA등록 비밀키': self.get(section, 'ip_product_qna_register_secret_key', ''),
'상품QnA조회 인증키': self.get(section, 'ip_product_qna_check_auth_key', ''),
'상품QnA조회 비밀키': self.get(section, 'ip_product_qna_check_secret_key', ''),
'인터파크 업체번호': self.get(section, 'ip_interpark_company_number', ''),
'공급계약 일련번호': self.get(section, 'ip_supply_contract_serial_number', '')
},
'위메프': {
'API KEY': self.get(section, 'wmp_api_key', '')
},
'옥션1.0': {
'API KEY': self.get(section, 'at_api_key', ''),
'멤버 ID': self.get(section, 'at_member_id', '')
}
}
def set_api_keys(self, business_id, api_keys):
business_section = f'BUSINESS_{business_id}'
if not self.config.has_section(business_section):
self.config.add_section(business_section)
for market, keys in api_keys.items():
for key_name, key_value in keys.items():
encrypted_value = self.encrypt(key_value)
self.config.set(business_section, f'{market}_{key_name}', encrypted_value)
with open(self.config_file, 'w') as configfile:
self.config.write(configfile)
def reset_settings(self):
if os.path.exists(self.config_file):
os.remove(self.config_file)
self._create_default_config()
self.config.read(self.config_file)
def get_user_info(self):
user_id = self.get('USER', 'user_id', fallback='')
encrypted_password = self.get('USER', 'password', fallback='')
password = self.decrypt(encrypted_password) if encrypted_password else ''
return user_id, password

8
utils/logger.py Normal file
View File

@ -0,0 +1,8 @@
from loguru import logger
import sys
def setup_logger(log_level="DEBUG"):
logger.remove()
logger.add(sys.stdout, level=log_level)
logger.add("app.log", level=log_level, rotation="10 MB", retention="10 days")
return logger

217
utils/playwright_helpers.py Normal file
View File

@ -0,0 +1,217 @@
from playwright.async_api import async_playwright
class PlaywrightHelper:
def __init__(self):
self.browser = None
async def init_browser(self):
playwright = await async_playwright().start()
self.browser = await playwright.chromium.launch(headless=False)
async def close_browser(self):
if self.browser:
await self.browser.close()
async def login_and_fetch_api_keys(self, url, username, password, status_label, progress_bar):
context = await self.browser.new_context()
page = await context.new_page()
await page.goto(url)
progress_bar.setValue(10)
status_label.setText('현재 상태: 웹페이지 접속완료')
# 홈 페이지에서 로그인 버튼 클릭
await page.click(".signList > .ant-btn-default > span")
# 로그인 페이지에서 로그인 수행
await page.fill(".ant-input:nth-child(4)", username)
await page.fill(".ant-input:nth-child(1)", password)
await page.click(".ant-btn-primary")
progress_bar.setValue(20)
status_label.setText('현재 상태: 퍼센티 로그인 완료')
# 팝업 다이얼로그 닫기 (있는 경우)
try:
await page.click("xpath=body > div:nth-child(10) > div > div.ant-modal-wrap.ant-modal-centered > div > div.ant-modal-content > div.ant-modal-footer > button.ant-btn.css-1li46mu.ant-btn-primary")
except:
pass
# 마켓 설정 페이지로 이동
await page.click("xpath=/html/body/div[1]/div/div/div/div/aside/div/ul/li[7]/ul/li[2]")
# await page.click("div#root li.ant-menu-item.ant-menu-item-selected.ant-menu-item-only-child > span")
progress_bar.setValue(30)
status_label.setText('현재 상태: 마켓 설정')
api_keys = {}
# 각 마켓별 API 키 가져오기
async def fetch_market_api_keys(market_xpath, api_key_xpaths):
await page.click(market_xpath)
await page.wait_for_timeout(1000) # 잠시 대기
return {key: await page.get_attribute(xpath, 'value') for key, xpath in api_key_xpaths.items()}
api_key_xpaths = {
'쿠팡': {
'쿠팡ID': "div#rc-tabs-0-panel-cp div:nth-child(1) > input",
'업체 코드': "div#rc-tabs-0-panel-cp div:nth-child(2) > input",
'Access Key': "div#rc-tabs-0-panel-cp div:nth-child(3) > input",
'Secret Key': "div#rc-tabs-0-panel-cp div:nth-child(4) > input",
},
'스마트스토어': {
'업로드항 스마트스토어 계정' : "div#rc-tabs-0-panel-ss div:nth-child(1) > input",
'애플리케이션 ID': "div#rc-tabs-0-panel-ss div:nth-child(3) > input",
'애플리케이션 시크릿': "div#rc-tabs-0-panel-ss div:nth-child(3) > input",
},
'옥션지마켓': {
'옥션ID': "div#rc-tabs-0-panel-esm div:nth-child(1) > input",
'G마켓 ID': "div#rc-tabs-0-panel-esm div:nth-child(2) > input",
},
'11번가-일반': {
'API KEY': "div#rc-tabs-0-panel-est input",
},
'11번가-글로벌': {
'API KEY': "div#rc-tabs-0-panel-est_global input",
},
'롯데온': {
'API KEY': "div#rc-tabs-0-panel-lotteon input",
},
'인터파크': {
'상품상태재고수정 인증키': "div#rc-tabs-0-panel-ip div:nth-child(1) > input",
'상품상태재고수정 비밀키':"div#rc-tabs-0-panel-ip div:nth-child(2) > input",
'상품재고조회 인증키':"div#rc-tabs-0-panel-ip div:nth-child(3) > input",
'상품재고조회 비밀키':"div#rc-tabs-0-panel-ip div:nth-child(4) > input",
'상품정보조회 인증':"div#rc-tabs-0-panel-ip div:nth-child(6) > input",
'상품정보조회 비밀키':"div#rc-tabs-0-panel-ip div:nth-child(7) > input",
'상품수정 인증키':"div#rc-tabs-0-panel-ip div:nth-child(8) > input",
'상품수정 비밀키':"div#rc-tabs-0-panel-ip div:nth-child(9) > input",
'상품등록 인증키':"div#rc-tabs-0-panel-ip div:nth-child(11) > input",
'상품등록 비밀키':"div#rc-tabs-0-panel-ip div:nth-child(12) > input",
'반품배송지조회 인증키':"div#rc-tabs-0-panel-ip div:nth-child(13) > input",
'반품배송지조회 비밀키':"div#rc-tabs-0-panel-ip div:nth-child(14) > input",
'반품배송지등록 인증키':"div#rc-tabs-0-panel-ip div:nth-child(16) > input",
'반품배송지등록 비밀키':"div#rc-tabs-0-panel-ip div:nth-child(17) > input",
'상품QnA등록 인증키':"div#rc-tabs-0-panel-ip div:nth-child(18) > input",
'상품QnA등록 비밀키':"div#rc-tabs-0-panel-ip div:nth-child(19) > input",
'상품QnA조회 인증키':"div#rc-tabs-0-panel-ip div:nth-child(21) > input",
'상품QnA조회 비밀키':"div#rc-tabs-0-panel-ip div:nth-child(22) > input",
'인터파크 업체번호':"div#rc-tabs-0-panel-ip div:nth-child(23) > input",
'공급계약 일련번호':"div#rc-tabs-0-panel-ip div:nth-child(24) > input",
},
'위메프': {
'API KEY': "div#rc-tabs-0-panel-wmp input",
},
'옥션1.0': {
'API KEY': "div#rc-tabs-0-panel-at div:nth-child(1) > input",
'멤버 ID': "div#rc-tabs-0-panel-at div:nth-child(2) > input",
},
}
api_keys['쿠팡'] = await fetch_market_api_keys("div#rc-tabs-0-tab-cp", api_key_xpaths['쿠팡'])
# print(f"api_keys['쿠팡'] \n {api_keys['쿠팡']}")
progress_bar.setValue(35)
status_label.setText('현재 상태: 쿠팡 가져오기 완료')
api_keys['스마트스토어'] = await fetch_market_api_keys("div#rc-tabs-0-tab-ss", api_key_xpaths['스마트스토어'])
# print(f"api_keys['스마트스토어'] \n {api_keys['스마트스토어']}")
progress_bar.setValue(40)
status_label.setText('현재 상태: 스마트스토어 가져오기 완료')
api_keys['옥션지마켓'] = await fetch_market_api_keys("div#rc-tabs-0-tab-esm", api_key_xpaths['옥션지마켓'])
# print(f"api_keys['옥션지마켓'] \n {api_keys['옥션지마켓']}")
progress_bar.setValue(45)
status_label.setText('현재 상태: ESM 가져오기 완료')
api_keys['11번가-일반'] = await fetch_market_api_keys("div#rc-tabs-0-tab-est", api_key_xpaths['11번가-일반'])
# print(f"api_keys['11번가-일반'] \n {api_keys['11번가-일반']}")
progress_bar.setValue(50)
status_label.setText('현재 상태: 11번가 국내 가져오기 완료')
api_keys['11번가-글로벌'] = await fetch_market_api_keys("div#rc-tabs-0-tab-est_global", api_key_xpaths['11번가-글로벌'])
# print(f"api_keys['11번가-글로벌'] \n {api_keys['11번가-글로벌']}")
progress_bar.setValue(55)
status_label.setText('현재 상태: 11번가 글로벌 가져오기 완료')
api_keys['롯데온'] = await fetch_market_api_keys("div#rc-tabs-0-tab-lotteon", api_key_xpaths['롯데온'])
# print(f"api_keys['롯데온'] \n {api_keys['롯데온']}")
progress_bar.setValue(60)
status_label.setText('현재 상태: 롯데온 가져오기 완료')
api_keys['인터파크'] = await fetch_market_api_keys("div#rc-tabs-0-tab-ip", api_key_xpaths['인터파크'])
# print(f"api_keys['인터파크'] \n {api_keys['인터파크']}")
progress_bar.setValue(65)
status_label.setText('현재 상태: 인터파크 가져오기 완료')
api_keys['위메프'] = await fetch_market_api_keys("div#rc-tabs-0-tab-wmp", api_key_xpaths['위메프'])
# print(f"api_keys['위메프'] \n {api_keys['위메프']}")
progress_bar.setValue(70)
status_label.setText('현재 상태: 위메프 가져오기 완료')
api_keys['옥션1.0'] = await fetch_market_api_keys("div#rc-tabs-0-tab-at", api_key_xpaths['옥션1.0'])
# print(f"api_keys['옥션1.0'] \n {api_keys['옥션1.0']}")
progress_bar.setValue(75)
status_label.setText('현재 상태: 옥션1.0 가져오기 완료')
await context.close()
return api_keys
async def update_api_keys(self, url, username, password, api_keys, status_label, progress_bar):
context = await self.browser.new_context()
page = await context.new_page()
await page.goto(url)
# 홈 페이지에서 로그인 버튼 클릭
await page.click(".signList > .ant-btn-default > span")
# 로그인 페이지에서 로그인 수행
await page.fill(".ant-input:nth-child(4)", username)
await page.fill(".ant-input:nth-child(1)", password)
await page.click(".ant-btn-primary")
# 팝업 다이얼로그 닫기 (있는 경우)
try:
await page.click("xpath=body > div:nth-child(10) > div > div.ant-modal-wrap.ant-modal-centered > div > div.ant-modal-content > div.ant-modal-footer > button.ant-btn.css-1li46mu.ant-btn-primary")
except:
pass
# 마켓 설정 페이지로 이동
await page.click("xpath=/html/body/div[1]/div/div/div/div/aside/div/ul/li[7]/ul/li[2]")
# await page.click("div#root li.ant-menu-item.ant-menu-item-selected.ant-menu-item-only-child > span")
# 각 마켓별 API 키 업데이트
async def update_market_api_keys(market_xpath, api_key_xpaths):
await page.click(market_xpath)
await page.wait_for_timeout(1000) # 잠시 대기
for key, value in api_key_xpaths.items():
await page.fill(value, api_keys.get(key, ''))
await update_market_api_keys("div#rc-tabs-0-tab-cp", api_keys['쿠팡'])
progress_bar.setValue(35)
status_label.setText('현재 상태: 쿠팡 업데이트 완료')
await update_market_api_keys("div#rc-tabs-0-tab-ss", api_keys['스마트스토어'])
progress_bar.setValue(40)
status_label.setText('현재 상태: 스마트스토어 업데이트 완료')
await update_market_api_keys("div#rc-tabs-0-tab-esm", api_keys['옥션지마켓'])
progress_bar.setValue(45)
status_label.setText('현재 상태: ESM 업데이트 완료')
await update_market_api_keys("div#rc-tabs-0-tab-est", api_keys['11번가-일반'])
progress_bar.setValue(50)
status_label.setText('현재 상태: 11번가 국내 업데이트 완료')
await update_market_api_keys("div#rc-tabs-0-tab-est_global", api_keys['11번가-글로벌'])
progress_bar.setValue(55)
status_label.setText('현재 상태: 11번가 글로벌 업데이트 완료')
await update_market_api_keys("div#rc-tabs-0-tab-lotteon", api_keys['롯데온'])
progress_bar.setValue(60)
status_label.setText('현재 상태: 롯데온 업데이트 완료')
await update_market_api_keys("div#rc-tabs-0-tab-ip", api_keys['인터파크'])
progress_bar.setValue(65)
status_label.setText('현재 상태: 인터파크 업데이트 완료')
await update_market_api_keys("div#rc-tabs-0-tab-wmp", api_keys['위메프'])
progress_bar.setValue(70)
status_label.setText('현재 상태: 위메프 업데이트 완료')
await update_market_api_keys("div#rc-tabs-0-tab-at", api_keys['옥션1.0'])
progress_bar.setValue(75)
status_label.setText('현재 상태: 옥션1.0 업데이트 완료')
await context.close()