From c539432fc1a116d0dcd64de4d1aa2d969eae90c5 Mon Sep 17 00:00:00 2001 From: HK-Mattew Date: Sat, 27 Apr 2024 16:58:13 -0300 Subject: [PATCH] First commit! --- .gitignore | 107 ++++++++++++++++++ LICENSE | 21 ++++ README.md | 40 +++++++ payeer_asyncio/__init__.py | 1 + payeer_asyncio/api.py | 187 ++++++++++++++++++++++++++++++++ payeer_asyncio/exceptions.py | 7 ++ payeer_asyncio/utils/account.py | 8 ++ requirements.txt | 1 + setup.py | 39 +++++++ 9 files changed, 411 insertions(+) create mode 100644 .gitignore create mode 100644 LICENSE create mode 100644 README.md create mode 100644 payeer_asyncio/__init__.py create mode 100644 payeer_asyncio/api.py create mode 100644 payeer_asyncio/exceptions.py create mode 100644 payeer_asyncio/utils/account.py create mode 100644 requirements.txt create mode 100644 setup.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a1b4f35 --- /dev/null +++ b/.gitignore @@ -0,0 +1,107 @@ +# Created by .ignore support plugin (hsz.mobi) +### Python template +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +.hypothesis/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +.static_storage/ +.media/ +local_settings.py + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# pyenv +.python-version + +# celery beat schedule file +celerybeat-schedule + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ + diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..c67e2ce --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2017 HK-Mattew + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..9ca6d93 --- /dev/null +++ b/README.md @@ -0,0 +1,40 @@ +# AsyncIO Payeer Client + +Implementation of AsyncIO Client for Payeer API. + +Before use, it is advisable to familiarize yourself with the official Payeer documentation (https://payeercom.docs.apiary.io/). The application implements the interaction protocol described in this document. + +## Installation + +``` +pip install git+https://github.com/HK-Mattew/python-payeer-asyncio +``` + +## Example of use + +```python +from payeer_asyncio import PayeerAsyncIO +import asyncio + + + +async def main(): + + + payeer = PayeerAsyncIO( + account='', + apiId='', + apiPass='' + ) + + + balance = await payeer.get_balance() + + print(balance) + + + + +if __name__ == "__main__": + asyncio.run(main()) +``` \ No newline at end of file diff --git a/payeer_asyncio/__init__.py b/payeer_asyncio/__init__.py new file mode 100644 index 0000000..15a81f2 --- /dev/null +++ b/payeer_asyncio/__init__.py @@ -0,0 +1 @@ +from .api import PayeerAsyncIO, PayeerAPIException \ No newline at end of file diff --git a/payeer_asyncio/api.py b/payeer_asyncio/api.py new file mode 100644 index 0000000..ec2780b --- /dev/null +++ b/payeer_asyncio/api.py @@ -0,0 +1,187 @@ +from .exceptions import PayeerAPIException +from .utils.account import validate_account +from typing import ( + Dict +) +import httpx +import copy + + + + +class PayeerAsyncIO: + """Payeer API Client""" + + def __init__(self, account: str, apiId: str, apiPass: str): + """ + :param account: Your account number in the Payeer. Example: P1000000 + :param apiId: The API user ID; given out when adding the API + :param apiPass: The API user's secret key + """ + self.account = account + self.apiId = apiId + self.apiPass = apiPass + self.api_url = 'https://payeer.com/ajax/api/api.php' + self.auth_data = { + 'account': self.account, + 'apiId': self.apiId, + 'apiPass': self.apiPass + } + + + async def request(self, **kwargs) -> Dict: + """The main request method for Payeer API""" + + data = copy.deepcopy(self.auth_data) + + if kwargs: + data.update(kwargs) + + async with httpx.AsyncClient() as client: + http_resp = await client.post(self.api_url, data=data) + resp_json = http_resp.json() + + error = resp_json.get('errors') + if error: + raise PayeerAPIException(error) + else: + return resp_json + + + async def get_balance(self): + """ + Balance Check + Obtain wallet balance. + """ + return (await self.request(action='balance'))['balance'] + + + async def check_user(self, user): + """ + Checking Existence of Account + :param user: user’s account number in the format P1000000 + :return: True if exists + """ + try: + await self.request(action='checkUser', user=user) + except PayeerAPIException: + return False + return True + + + async def get_exchange_rate(self, output='N'): + """ + Automatic Conversion Rates + :param output: select currencies for conversion rates (N - get deposit rates Y - get withdrawal rates) + :return: dict + """ + return (await self.request(action='getExchangeRate', output=output))['rate'] + + + async def get_pay_systems(self): + """ + Getting Available Payment Systems + :return: dict + """ + return (await self.request(action='getPaySystems'))['list'] + + + async def get_history_info(self, history_id): + """ + Getting Information about a Transaction + :param history_id: transaction ID + :return: dict + """ + return (await self.request(action='historyInfo', historyId=history_id))['info'] + + + async def shop_order_info(self, shop_id, order_id): + """ + Information on a Store Transaction + :param shop_id: merchant ID (m_shop) + :param order_id: transaction ID in your accounting system (m_orderid) + :return: dict + """ + return await self.request(action='shopOrderInfo', shopId=shop_id, orderId=order_id) + + + async def transfer(self, sum, to, cur_in='USD', cur_out='USD', + comment=None, protect=None, protect_period=None, protect_code=None): + """ + Transferring Funds + :param sum: amount withdrawn (the amount deposited will be calculated automatically, factoring in all fees from the recipient) + :param to: user’s Payeer account number or email address + :param cur_in: currency with which the withdrawal will be performed (USD, EUR, RUB) + :param cur_out: deposit currency (USD, EUR, RUB) + :param comment: comments on the transfer + :param protect: activation of transaction protection, set Y to enable + :param protect_period: protection period: 1–30 days + :param protect_code: protection code + :return: True if the payment is successful + """ + await validate_account(to) + data = {'action': 'transfer', 'sum': sum, 'to': to, 'curIn': cur_in, 'curOut': cur_out} + if comment: + data['comment'] = comment + if protect: + data['protect'] = protect + if protect_period: + data['protectPeriod'] = protect_period + if protect_code: + data['protectCode'] = protect_code + + return await self.request(**data) + + + async def check_output(self, ps, ps_account, sum_in, cur_in='USD', cur_out='USD'): + """ + Checking Possibility of Payout + This method allows you to check the possibility of a payout without actually creating a payout + (you can get the withdrawal/reception amount or check errors in parameters) + :param ps: ID of selected payment system + :param ps_account: recipient's account number in the selected payment system + :param sum_in: amount withdrawn (the amount deposited will be calculated automatically, factoring in all fees from the recipient) + :param cur_in: currency with which the withdrawal will be performed + :param cur_out: deposit currency + :return: True if the payment is successful + """ + data = {'action': 'initOutput', 'ps': ps, 'param_ACCOUNT_NUMBER': ps_account, + 'sumIn': sum_in, 'curIn': cur_in, 'curOut': cur_out} + try: + await self.request(**data) + except PayeerAPIException: + return False + return True + + + async def output(self, ps, ps_account, sum_in, cur_in='USD', cur_out='USD'): + """ + Payout + :param ps: ID of selected payment system + :param ps_account: recipient's account number in the selected payment system + :param sum_in: amount withdrawn (the amount deposited will be calculated automatically, factoring in all fees from the recipient) + :param cur_in: currency with which the withdrawal will be performed + :param cur_out: deposit currency + :return: + """ + data = {'action': 'output', 'ps': ps, 'param_ACCOUNT_NUMBER': ps_account, + 'sumIn': sum_in, 'curIn': cur_in, 'curOut': cur_out} + return await self.request(**data) + + + async def history(self, **kwargs): + """ + History of transactions + :param sort: sorting by date (asc, desc) + :param count: count of records (max 1000) + :param from: begin of the period + :param to: end of the period + :param type: transaction type (incoming - incoming payments, outgoing - outgoing payments) + :param append: id of the previous transaction + :return: + """ + kwargs['action'] = 'history' + return (await self.request(**kwargs))['history'] + + + diff --git a/payeer_asyncio/exceptions.py b/payeer_asyncio/exceptions.py new file mode 100644 index 0000000..ae18f58 --- /dev/null +++ b/payeer_asyncio/exceptions.py @@ -0,0 +1,7 @@ + + + +class PayeerAPIException(Exception): + """Base payeer api exception class""" + + diff --git a/payeer_asyncio/utils/account.py b/payeer_asyncio/utils/account.py new file mode 100644 index 0000000..f4d4966 --- /dev/null +++ b/payeer_asyncio/utils/account.py @@ -0,0 +1,8 @@ +import re + + +async def validate_account(wallet): + if not re.match("^[Pp]{1}[0-9]{7,15}|.+@.+\..+$", wallet): + raise ValueError('Wrong account format!') + + diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..72c64de --- /dev/null +++ b/requirements.txt @@ -0,0 +1 @@ +httpx ~= 0.27 \ No newline at end of file diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..b8bbb1a --- /dev/null +++ b/setup.py @@ -0,0 +1,39 @@ +#!/usr/bin/env python +from typing import ( + List +) +from pathlib import Path +from setuptools import setup + + + + +def get_requirements() -> List[str]: + """Build the requirements list for this project""" + requirements_list = [] + + with Path("requirements.txt").open(encoding="UTF-8") as reqs: + for install in reqs: + if install.startswith("#"): + continue + requirements_list.append(install.strip()) + + return requirements_list + + + + +setup( + name='python-payeer-asyncio', + version='0.1', + description='AsyncIO Payeer Client', + long_description=Path('README.md').read_text(encoding='UTF-8'), + author='HK-Mattew', + author_email='not-found@localhost.local', + url='https://github.com/HK-Mattew/python-payeer-asyncio', + packages=['payeer_asyncio'], + requires=get_requirements(), + license='MIT license', + keywords=['payeer', 'payeer asyncio', 'payeer async'] + ) +