# coding=utf-8 import requests import sys import time import pprint from optparse import OptionParser HOST, PORT = "localhost", 8080 url = 'http://%s:%s/' % (HOST, PORT) url_start = 'http://admin:Azaraza45@%s:%s/' % (HOST, PORT) dictionary_url = url + "dicts/" docs_url = url + "docs/" EAC_REST_API_COOKIE_NAME = "EACRestAPISession" EAC_REST_API_COOKIE = dict() def generate_agreement_data(me, him): return { "a_id": "OMVHD8CMUEEE8Z1J4TJ3", # внутренний идентифиратор заключаемого договора "agrnum DONT_SPECIFY" : "TRN98.ХХ", "comment_1" : "Номер договора не указывается при создании.", "agrtype" : 1, "comment_2" : "тип договора: 1 по ЦБ, 2 - по товарам", "status" : "asDraft", "comment_4" : "Возможные значения при создании: asDraft, asConfPresign", "issuec" : "GAZPS", "comment_5" : "Код ценной бумаги или товара", "unitsn" : 10.0, "comment_6" : "Количество ценной бумаги или товара", "unitpr" : 1000.0, "comment_7": "Цена одной ЦБ", "dealpr" : 10000.0, "comment_8": "Сумма договора, исчисляемая в валюте сделки", "trdcur" : "USD", "comment_9": "Валюта сделки", "paycur" : "USD", "comment_10": "Валюта платежа", "brtscd" : me, "comment_11": "Покупатель в лице. Код Участника в РТС", "srtscd" : him, "comment_12": "Продавец в лице. Код Участника в РТС", "paydat_d DONT_SPECIFY": "20210113", "comment_13": "Дата оплаты - не указывается одновременно со сроком оплаты", "paydat_t" : 5, "comment_14": "Срок оплаты - не указывается одновременно с датой оплаты", "payfro" : "A", "comment_15" : "Срок оплаты исчисляется: A - с даты договора, D - с даты поставки ЦБ, N - другое", "deldat_t" : 3, "comment_16" : "Срок поставки ЦБ", "delfro" : "P", "comment_17" : "Срок перерегистрации исчисляется: A - с даты договора, P - с даты оплаты, N - другое, F - с даты предоплаты(для товарных договоров)", "incoming" : 0, "regist_c" : "D", "bclicd" : "AZ00010", "settyp" : 2, "regpar" : 2, "anotes" : "Указываются дополнительные условия договора, отличные от стандартных", "bondpr" : 0.0, "accint" : 0.0, "sur_flag" : 0, "bparnm_c" : me, "bbankn_c" : "CITIDVP", "baccnb" : "8678678756453737650", "bracct" : 1, "brgacc" : "122100001", "sracct" : 0, "tradenum" : 0, "bladdr" : "тута", "baddrs" : "Ленинград точка ру", "bbinfo" : "ИНН:768787978798, други рыквызыты", "bclinm_n" : "X", "baccow_n" : "1221", "bregnm_n" : "1221", "bclist" : "RUS", "cc_dealpr" : 0.0, "brgdoc" : "орпвоопво от 01.01.2020 выдан паопаоароароаевопсв", "brgagr" : "ДД-1221 N9999 от 01.01.2020", "bregnn" : "768787978798", "comments": "Комментарии писать тут", # "cc_status": "Указываются какие-то коды типа AAA,AAB,AAC,AAD, и прочая дополнительная информация" } def print_pretty(obj, file_name=None): out = open(file_name, 'wt') if file_name else sys.stdout printer = pprint.PrettyPrinter(stream=out) printer.pprint(obj) sys.stdout.flush() class BColors: OK = '\033[92m' FAIL = '\033[91m' ENDC = '\033[0m' INFO = '\033[34m' def load_dictionary(dict_name): # print(BColors.INFO + 'TEST: Запрос справочника банков' + BColors.ENDC) dict_path = { 'clients': 'clients', 'schema': 'schema', 'bankacc': 'bankacc', 'banks': 'banks', 'depos': 'depos', 'depoacc': 'depoacc', } dicts_reply_packet_name = { 'clients': 'eClientsReply', 'schema': 'eSchemasReply', 'bankacc': 'eBankAccReply', 'banks': 'eBanksReply', 'depos': 'eDeposReply', 'depoacc': 'eDepoAccReply', } reply = requests.get('http://localhost:%s/dicts/%s' % (PORT,dict_path[dict_name]), cookies=EAC_REST_API_COOKIE) if reply.ok: # and reply.json()['dataHeader']['type'] == dicts_reply_packet_name[dict_name] # print(BColors.OK + "PASS" + BColors.ENDC) return reply.json() else: print(BColors.FAIL + "FAILED loadinng dictionary " + dict_name + BColors.ENDC) return None def generate_outcoming_bid(agreement_data): agrnum = '' print(BColors.INFO + 'TEST: Создание договора' + BColors.ENDC) reply = requests.post(docs_url + 'agreement', json=agreement_data, cookies=EAC_REST_API_COOKIE) if not reply.ok: print(reply) if reply.ok: agrnum = reply.json()['m_str'] print(BColors.OK + ("PASSED Создан новый договор %s" % agrnum) + BColors.ENDC) else: print(BColors.FAIL + "FAILED" + BColors.ENDC) agreement_filter = "agrnum = '%s'" % agrnum print(BColors.INFO + 'TEST: Получение договора в списке договоров' + BColors.ENDC) reply = requests.get(docs_url + 'agreements/' + agrnum, cookies=EAC_REST_API_COOKIE) if not reply.ok: print(reply) if reply.ok and len(reply.json()) == 1: agreement = reply.json()[0] assert agreement['agrnum'] == agrnum assert agreement['a_id'] == agreement_data['a_id'] print(BColors.OK + ("PASSED получен договор %s" % agrnum) + BColors.ENDC) else: print(BColors.FAIL + "FAILED" + BColors.ENDC) print(BColors.INFO + 'TEST: Получение договора' + BColors.ENDC) reply = requests.get(docs_url + 'agreement/' + agrnum, cookies=EAC_REST_API_COOKIE) if not reply.ok: print(reply) if reply.ok: agreement_v1 = reply.json() assert agreement_v1['agrnum'] == agrnum assert agreement_v1['a_id'] == agreement_data['a_id'] print(BColors.OK + ("PASSED получен договор %s" % agrnum) + BColors.ENDC) # print(agreement_v1) else: print(BColors.FAIL + "FAILED" + BColors.ENDC) print(BColors.INFO + 'TEST: Утверждение договора' + BColors.ENDC) agreement_v1['status'] = 'asConfPresign' reply = requests.put(docs_url + 'agreement/' + agrnum, json=agreement_v1, cookies=EAC_REST_API_COOKIE) if not reply.ok: print(reply) # print(reply.json()) if reply.ok: print(BColors.OK + ("PASSED Утвержден договор %s" % agrnum) + BColors.ENDC) # assert reply.json()['dataHeader']['type'] == 'eUpdateReply' reply = requests.get(docs_url + 'agreement/' + agrnum, cookies=EAC_REST_API_COOKIE) assert reply.ok # assert reply.json()['dataHeader']['type'] == 'eAgrReply' assert reply.json()['status'] == 'asConfPresign' else: print(BColors.FAIL + "FAILED" + BColors.ENDC) print(BColors.INFO + 'TEST: Отсылка договора контрагенту' + BColors.ENDC) agreement_v1['status'] = 'asConfSigned' reply = requests.put(docs_url + 'agreement/' + agrnum, json=agreement_v1, cookies=EAC_REST_API_COOKIE) if not reply.ok: print(reply) if reply.ok: print(BColors.OK + ("PASSED Отослан договор %s" % agrnum) + BColors.ENDC) # assert reply.json()['dataHeader']['type'] == 'eUpdateReply' reply = requests.get(docs_url + 'agreement/' + agrnum, cookies=EAC_REST_API_COOKIE) assert reply.ok # assert reply.json()['dataHeader']['type'] == 'eAgrReply' assert reply.json()['status'] == 'asConfSent' agreement_v1 = reply.json() else: print(BColors.FAIL + "FAILED" + BColors.ENDC) print(BColors.INFO + 'TEST: Запрос подписей договора' + BColors.ENDC) reply = requests.get(docs_url + 'agreement/' + agrnum + '/signatures', cookies=EAC_REST_API_COOKIE) if not reply.ok: print(reply.json()) if reply.ok: print(BColors.OK + ("PASSED подписи договора %s получены" % agrnum) + BColors.ENDC) # assert reply.json()['dataHeader']['type'] == 'eSignatureAttributesReply' # из-за того, что подписи обрабатываются отдельным сигналом, в сервере может случится так, что # формирование подписей после отсылки может ещё не произойти в этот момент, и список подписей будет пустой. # assert len(reply.json()) > 1 # print_pretty(reply.json()) else: print(BColors.FAIL + "FAILED" + BColors.ENDC) print(BColors.OK + ("ОЖИДАНИЕ РАССМОТРЕНИЯ договора %s контрагентом" % agrnum) + BColors.ENDC) wait_count = 0 while not (agreement_v1['status'] == 'asOfferReceived' or agreement_v1['status'] == 'asConfDenialReceived'): time.sleep(10) wait_count += 1 print(BColors.OK + 'ждём ' + '.'*wait_count + BColors.ENDC) reply = requests.get(docs_url + 'agreement/' + agrnum, cookies=EAC_REST_API_COOKIE) assert reply.ok # assert reply.json()['dataHeader']['type'] == 'eAgrReply' if agreement_v1['status'] != reply.json()['status']: print(BColors.INFO + 'статус изменился ' + agreement_v1['status'] + '->' + reply.json()['status'] + BColors.ENDC) agreement_v1 = reply.json() print(BColors.OK + ("PASSED договор %s рассмотрен контрагентом" % agrnum) + BColors.ENDC) # Контрагент (продавец) подтвердил договор if agreement_v1['status'] == 'asOfferReceived': print(BColors.INFO + 'TEST: Передача покупки на подпись' + BColors.ENDC) agreement_v1['status'] = 'asAcceptPresign' reply = requests.put(docs_url + 'agreement/' + agrnum, json=agreement_v1, cookies=EAC_REST_API_COOKIE) if not reply.ok: print(reply) if reply.ok: print(BColors.OK + ("PASSED договор %s переведён на окончательную подпись" % agrnum) + BColors.ENDC) # assert reply.json()['dataHeader']['type'] == 'eUpdateReply' reply = requests.get(docs_url + 'agreement/' + agrnum, cookies=EAC_REST_API_COOKIE) assert reply.ok # assert reply.json()['dataHeader']['type'] == 'eAgrReply' assert reply.json()['status'] == 'asAcceptPresign' agreement_v1 = reply.json() else: print(BColors.FAIL + "FAILED" + BColors.ENDC) return print(BColors.INFO + 'TEST: Подтверждение покупки' + BColors.ENDC) agreement_v1['status'] = 'asAcceptSigned' reply = requests.put(docs_url + 'agreement/' + agrnum, json=agreement_v1, cookies=EAC_REST_API_COOKIE) if not reply.ok: print(reply) if reply.ok: print(BColors.OK + ("PASSED договор %s окончательную подписан" % agrnum) + BColors.ENDC) # assert reply.json()['dataHeader']['type'] == 'eUpdateReply' reply = requests.get(docs_url + 'agreement/' + agrnum, cookies=EAC_REST_API_COOKIE) assert reply.ok # assert reply.json()['dataHeader']['type'] == 'eAgrReply' assert reply.json()['status'] == 'asAcceptSigned' or reply.json()['status'] == 'asAcceptSent' # 'asAcceptOk' agreement_v1 = reply.json() else: print(BColors.FAIL + "FAILED" + BColors.ENDC) return print(BColors.OK + ("ОЖИДАНИЕ РЕГИСТРАЦИИ договора %s" % agrnum) + BColors.ENDC) wait_count = 0 while not (agreement_v1['status'] == 'asAgreementRegistered'): # agreement_v1['status'] == 'asAcceptOk' or time.sleep(10) wait_count += 1 print(BColors.OK + 'ждём ' + '.' * wait_count + BColors.ENDC) reply = requests.get(docs_url + 'agreement/' + agrnum, cookies=EAC_REST_API_COOKIE) assert reply.ok # assert reply.json()['dataHeader']['type'] == 'eAgrReply' if agreement_v1['status'] != reply.json()['status']: print(BColors.INFO + 'статус изменился ' + agreement_v1['status'] + '->' + reply.json()[ 'status'] + BColors.ENDC) agreement_v1 = reply.json() print(BColors.OK + ("PASSED договор %s зарегистрирован" % agrnum) + BColors.ENDC) print(BColors.INFO + 'TEST: Запрос подписей договора' + BColors.ENDC) reply = requests.get(docs_url + 'agreement/' + agrnum + '/signatures', cookies=EAC_REST_API_COOKIE) if not reply.ok: print(reply) if reply.ok: print(BColors.OK + ("PASSED подписи договора %s получены" % agrnum) + BColors.ENDC) # assert reply.json()['dataHeader']['type'] == 'eSignatureAttributesReply' assert len(reply.json()) > 1 else: print(BColors.FAIL + "FAILED" + BColors.ENDC) return else: print(BColors.INFO + 'TEST: Подтверждение отказа от продажи' + BColors.ENDC) agreement_v1['status'] = 'asPresign' reply = requests.put(docs_url + 'agreement/' + agrnum, json=agreement_v1, cookies=EAC_REST_API_COOKIE) if not reply.ok: print(reply) if reply.ok: print(BColors.OK + ("PASSED договор %s переведён на окончательную подпись" % agrnum) + BColors.ENDC) # assert reply.json()['dataHeader']['type'] == 'eUpdateReply' reply = requests.get(docs_url + 'agreement/' + agrnum, cookies=EAC_REST_API_COOKIE) assert reply.ok # assert reply.json()['dataHeader']['type'] == 'eAgrReply' assert reply.json()['status'] == 'asXXXXXXX' agreement_v1 = reply.json() else: print(BColors.FAIL + "FAILED" + BColors.ENDC) return def test_agr_bid(agreement_data): print(BColors.OK + "ГЕНЕРАЦИЯ запросов на покупку к контрагенту" + BColors.ENDC) bid_count = 0 BIDS_TO_PROCESS = 10000 while bid_count < BIDS_TO_PROCESS: bid_count += 1 generate_outcoming_bid(agreement_data) pass def test_agr_ask(): print(BColors.OK + "ОЖИДАНИЕ предложений от контрагентов" + BColors.ENDC) ask_count = 0 ASKS_TO_PROCESS = 10000 wait_count = 0 while ask_count < ASKS_TO_PROCESS: if wait_count > 0: print(BColors.OK + 'ждём ' + '.' * wait_count + BColors.ENDC) time.sleep(10) wait_count += 1 reply = requests.get(docs_url + 'agreements', cookies=EAC_REST_API_COOKIE) assert reply.ok agreement_list = reply.json() for agreement in filter(lambda e: e['status'] in ('asConfReceived', 'asOfferDraft'), agreement_list): ask_count += 1 agrnum = agreement['agrnum'] confirm_incoming_bid(agrnum) wait_count = 0 if not ask_count < ASKS_TO_PROCESS: break pass def build_depo_agr(dacc): return dacc['depo_agr_auth'] if dacc['depo_agr_auth'] else '' \ + ((" № " + dacc['depo_agr_num']) if dacc['depo_agr_num'] else '') \ + ((" от " + dacc['depo_agr_date']) if dacc['depo_agr_date'] else '') def build_depo_doc(dacc): return dacc['reg_num'] if dacc['reg_num'] else '' + \ ((" от " + dacc['reg_dat']) if dacc['reg_dat'] else '') + \ ((" выдан " + dacc['reg_auth']) if dacc['reg_auth'] else '') def confirm_incoming_bid(agrnum): print(BColors.OK + ("поступил новый договор %s" % agrnum) + BColors.ENDC) clients = load_dictionary('clients') schemata = load_dictionary('schema') bank_accounts = load_dictionary('bankacc') banks = load_dictionary('banks') depositiries = load_dictionary('depos') depo_accounts = load_dictionary('depoacc') reply = requests.get(docs_url + 'agreement/' + agrnum, cookies=EAC_REST_API_COOKIE) if not reply.ok: print(reply) assert reply.ok and reply.json()['agrnum'] == agrnum agreement = reply.json() client_id = next(filter(lambda c: c['code'] == agreement['srtscd'], clients))['id'] schema = schemata[0] # ВНИМАНИЕ! Поле идентификатора банковского счёта называется bank_id # это именно банковский счёт (bankacc) bank_account = next(filter(lambda b: b['id'] == schema['bank_id'], bank_accounts)) bank = next(filter(lambda b: b['id'] == bank_account['bank'], banks)) # ВНИМАНИЕ! Поле идентификатора счёта депозитария называется depo_id # это именно счёт депозитария, а не сам депозитарий depo_account = next(filter(lambda da: da['id'] == schema['depo_id'], depo_accounts)) # depo = next(filter(lambda d: d['id'] == depo_account['depo'],depositiries)) print(BColors.INFO + 'TEST: Ответить на договор' + agrnum + BColors.ENDC) agreement['status'] = 'asOfferDraft' reply = requests.put(docs_url + 'agreement/' + agrnum, json=agreement, cookies=EAC_REST_API_COOKIE) if not reply.ok: print(reply) # print(reply.json()) if reply.ok: print(BColors.OK + ("PASSED Отвечено на договор %s" % agrnum) + BColors.ENDC) # assert reply.json()['dataHeader']['type'] == 'eUpdateReply' reply = requests.get(docs_url + 'agreement/' + agrnum, cookies=EAC_REST_API_COOKIE) assert reply.ok # assert reply.json()['dataHeader']['type'] == 'eAgrReply' assert reply.json()['status'] == 'asOfferDraft' agreement = reply.json() else: print(BColors.FAIL + "FAILED" + BColors.ENDC) return print(BColors.INFO + 'TEST: договор на подпись ' + agrnum + BColors.ENDC) agreement['seller_id'] = client_id # ВАЖНО: поле 'sclinm_n' не должно быть пустым, содержание его неважно agreement['sclinm_n'] = 'X' agreement['seller_sch_id'] = schema['id'] agreement['sclicd'] = schema['pair'] agreement['sclist'] = schema['country'] # ВАЖНО! Задаётся либо код банка, либо наименование банка, но не оба поля сразу agreement['sbankn_c'] = bank['code'] # agreement['sbankn_n'] = bank['name'] agreement['sbankn_n'] = '' agreement['saccow_n'] = bank_account['bank_owner'] agreement['seller_bacc_id'] = bank_account['id'] agreement['saccnb'] = bank_account['bank_acc'] agreement['sbinfo'] = bank_account['bank_info'] agreement['sregnn'] = bank_account['inn'] agreement['seller_dacc_id'] = depo_account['id'] agreement['sracct'] = depo_account['depo_acc_type'] agreement['srgacc'] = depo_account['depo_acc'] agreement['sregnm_n'] = depo_account['depo_owner'] agreement['srgdoc'] = build_depo_doc(depo_account) agreement['srgagr'] = build_depo_agr(depo_account) agreement['status'] = 'asOfferPresign' # ВАЖНО! Нельзя менять параметры, определяющие суть сделки, # Это не проверяется клиентом, но сервер ЦЭД позже отклонит сделку. # agreement["unitpr"] = 42 reply = requests.put(docs_url + 'agreement/' + agrnum, json=agreement, cookies=EAC_REST_API_COOKIE) if not reply.ok: print(reply) # print(reply.json()) if reply.ok: print(BColors.OK + ("PASSED договор %s передан на подпись" % agrnum) + BColors.ENDC) # assert reply.json()['dataHeader']['type'] == 'eUpdateReply' reply = requests.get(docs_url + 'agreement/' + agrnum, cookies=EAC_REST_API_COOKIE) assert reply.ok # assert reply.json()['dataHeader']['type'] == 'eAgrReply' assert reply.json()['status'] == 'asOfferPresign' else: print(BColors.FAIL + "FAILED" + BColors.ENDC) return print(BColors.INFO + 'TEST: подписать договор ' + agrnum + BColors.ENDC) agreement['status'] = 'asOfferSigned' reply = requests.put(docs_url + 'agreement/' + agrnum, json=agreement, cookies=EAC_REST_API_COOKIE) if not reply.ok: print(reply) # print(reply.json()) if reply.ok: print(BColors.OK + ("PASSED договор %s подписан" % agrnum) + BColors.ENDC) # assert reply.json()['dataHeader']['type'] == 'eUpdateReply' reply = requests.get(docs_url + 'agreement/' + agrnum, cookies=EAC_REST_API_COOKIE) assert reply.ok # assert reply.json()['dataHeader']['type'] == 'eAgrReply' assert reply.json()['status'] in ('asOfferSigned', 'asOfferSent', 'asOfferOk') else: print(BColors.FAIL + "FAILED " + reply.json()['m_str'] + BColors.ENDC) # print_pretty(reply.json()) return # --------------------------------------------------------------------------------------------------------------------- # MAIN # --------------------------------------------------------------------------------------------------------------------- def main(): parser = OptionParser(usage='eacparser.py ...') parser.add_option("-s", "--seller", dest="seller", action="store_true", default=True, help="Are you a seller?") parser.add_option("-b", "--buyer", dest="buyer", action="store_true", default=False, help="Are you a buyer?") parser.add_option("-c", "--contra", dest="contra", help="Code of your contragent in all deals") (options, args) = parser.parse_args() if options.contra is None: print("--contra parameter is mandatory") quit() if options.buyer: options.seller = False ver_major = 0 ver_minor = 0 # connect to the service and get session cookie reply = requests.get(url_start + 'sys/parameter/major') if reply: print(BColors.OK + "SESSION OPENED " + reply.cookies[EAC_REST_API_COOKIE_NAME] + BColors.ENDC) global EAC_REST_API_COOKIE EAC_REST_API_COOKIE = dict(reply.cookies) ver_major = int(reply.json()['value']) else: print(BColors.FAIL + "FAILED logging in " + BColors.ENDC) quit() reply = requests.get(url_start + 'sys/parameter/minor', cookies=EAC_REST_API_COOKIE) if reply: ver_minor = int(reply.json()['value']) if ver_major >= 3 and ver_minor >= 11: print(BColors.OK + ("VERSION CHECKED: %s.%s " % (ver_major, ver_minor)) + BColors.ENDC) else: print(BColors.FAIL + ("WRONG EAC VERSION: %s.%s " % (ver_major, ver_minor)) + BColors.ENDC) reply = requests.get(url_start + 'sys/parameter/rts_id', cookies=EAC_REST_API_COOKIE) if options.buyer: buyer = reply.json()['value'] seller = options.contra if buyer != options.contra else "?????" data = generate_agreement_data(buyer, seller) test_agr_bid(data) elif options.seller: seller = reply.json()['value'] buyer = options.contra if seller != options.contra else "?????" test_agr_ask() pass if __name__ == '__main__': main()