Skip to content

(fix) issue #2: docs - webhook #16

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 1 addition & 7 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,10 @@ python:
- "3.9"
- "3.8"
- "3.7"
- "3.6"
- "3.5"
matrix:
include:
- python: 3.4
- python: 3.8
dist: xenial
- python: 2.7
before_install:
- pip install -U mock
- pip install -U pytest
# command to install dependencies
install:
- pip install -r requirements.txt && pip install -e .
Expand Down
2 changes: 1 addition & 1 deletion README.en.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ This product is used for managing payments under [The YooKassa API](https://yook
For usage by those who implemented YooKassa using the API method.

## Requirements
1. Python 2.7 or Python 3.x
1. Python >=3.7
2. pip

## Installation
Expand Down
8 changes: 5 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# YooKassa API Python Client Library
# YooKassa ASync API Python Client Library

[![Build Status](https://travis-ci.org/yoomoney/yookassa-sdk-python.svg?branch=master)](https://travis-ci.org/yoomoney/yookassa-sdk-python)
[![Latest Stable Version](https://img.shields.io/pypi/v/yookassa.svg)](https://pypi.org/project/yookassa/)
Expand All @@ -10,9 +10,11 @@ Russian | [English](https://github.com/yoomoney/yookassa-sdk-python/blob/master/
Клиент для работы с платежами по [API ЮKassa](https://yookassa.ru/developers/api)
Подходит тем, у кого способ подключения к ЮKassa называется API.

Асинхронная версия.

## Требования

1. Python 2.7 or Python 3.x
1. Python >=3.7
2. pip

## Установка
Expand Down Expand Up @@ -113,4 +115,4 @@ Configuration.configure_user_agent(
* [Запрос на создание чека](https://github.com/yoomoney/yookassa-sdk-python/blob/master/docs/examples/04-receipts.md#Запрос-на-создание-чека)
* [Запрос на создание чека через билдер](https://github.com/yoomoney/yookassa-sdk-python/blob/master/docs/examples/04-receipts.md#Запрос-на-создание-чека-через-билдер)
* [Получить информацию о чеке](https://github.com/yoomoney/yookassa-sdk-python/blob/master/docs/examples/04-receipts.md#Получить-информацию-о-чеке)
* [Получить список чеков с фильтрацией](https://github.com/yoomoney/yookassa-sdk-python/blob/master/docs/examples/04-receipts.md#Получить-список-чеков-с-фильтрацией)
* [Получить список чеков с фильтрацией](https://github.com/yoomoney/yookassa-sdk-python/blob/master/docs/examples/04-receipts.md#Получить-список-чеков-с-фильтрацией)
3 changes: 1 addition & 2 deletions docs/examples/01-configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,7 @@ var_dump.var_dump(me)

```python
import var_dump as var_dump
from yookassa import Webhook
from yookassa.domain.notification import WebhookNotificationEventType
from yookassa.domain.notification import WebhookNotification, WebhookNotificationEventType

whUrl = 'https://merchant-site.ru/payment-notification'
needWebhookList = [
Expand Down
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
httpx
requests
setuptools
urllib3
Expand Down
13 changes: 5 additions & 8 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
For usage by those who implemented YooKassa using the API method.

## Requirements
1. Python 2.7 or Python 3.x
1. Python >=3.7
2. pip

## Installation
Expand Down Expand Up @@ -102,7 +102,7 @@
version = re.search(r"__version__\s*=\s*'(.*)'", fp.read()).group(1)

setup(
name="yookassa",
name="yookassa-async",
author="YooMoney",
author_email="cms@yoomoney.ru",
version=version,
Expand All @@ -113,17 +113,14 @@
url="https://github.com/yoomoney/yookassa-sdk-python",
package_dir={"": "src"},
packages=find_packages('src'),
install_requires=["requests", "urllib3", "netaddr", "distro", "deprecated"],
install_requires=["httpx", "requests", "urllib3", "netaddr", "distro", "deprecated"],
zip_safe=False,
license="MIT",
classifiers=[
"License :: OSI Approved :: MIT License",
"Programming Language :: Python :: 2.7",
"Programming Language :: Python :: 3.4",
"Programming Language :: Python :: 3.5",
"Programming Language :: Python :: 3.6",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9"
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10"
]
)
64 changes: 49 additions & 15 deletions src/yookassa/client.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,50 @@
# -*- coding: utf-8 -*-
import requests
from requests.adapters import HTTPAdapter
import typing
import httpx
import time
from requests.auth import _basic_auth_str
from urllib3 import Retry

from yookassa import Configuration
from yookassa.domain.common import RequestObject, UserAgent
from yookassa.domain.exceptions import ApiError, BadRequestError, ForbiddenError, NotFoundError, \
ResponseProcessingError, TooManyRequestsError, UnauthorizedError


class RetryTransport(httpx.HTTPTransport):
""" Адаптация urllib3.Retry для HTTPX """

def __init__(self, *args, total: int = 3, backoff_factor: float = 1, method_whitelist: typing.Optional[list] = None, status_forcelist: typing.Optional[list] = None, **kwargs):
super(RetryTransport, self).__init__(*args, **kwargs)
self.total = total
self.backoff_factor = backoff_factor
self.method_whitelist = method_whitelist
self.status_forcelist = status_forcelist

def handle_request(
self,
request: httpx.Request,
) -> httpx.Response:
retry = 0
resp = None
retry_active = not self.method_whitelist or request.method in self.method_whitelist
while retry < self.total:
retry += 1
if retry > 2:
time.sleep(self.backoff_factor)
try:
if resp is not None:
resp.close()
resp = super().handle_request(request)
except Exception:
if not retry_active:
raise
continue
if self.status_forcelist and resp.status_code in self.status_forcelist:
continue
break
return resp


class ApiClient:
endpoint = Configuration.api_endpoint()

Expand All @@ -29,35 +64,34 @@ def __init__(self):
if self.configuration.agent_module:
self.user_agent.module = self.configuration.agent_module

def request(self, method="", path="", query_params=None, headers=None, body=None):
async def request(self, method="", path="", query_params=None, headers=None, body=None):
if isinstance(body, RequestObject):
body.validate()
body = dict(body)

request_headers = self.prepare_request_headers(headers)
raw_response = self.execute(body, method, path, query_params, request_headers)
raw_response = await self.execute(body, method, path, query_params, request_headers)

if raw_response.status_code != 200:
self.__handle_error(raw_response)

return raw_response.json()

def execute(self, body, method, path, query_params, request_headers):
async def execute(self, body, method, path, query_params, request_headers):
session = self.get_session()
raw_response = session.request(method,
self.endpoint + path,
f'{self.endpoint}{path}',
params=query_params,
headers=request_headers,
json=body)
json=body,
timeout=None)
return raw_response

def get_session(self):
session = requests.Session()
retries = Retry(total=self.max_attempts,
backoff_factor=self.timeout / 1000,
method_whitelist=['POST'],
status_forcelist=[202])
session.mount('https://', HTTPAdapter(max_retries=retries))
def get_session(self) -> httpx.Client:
session = httpx.Client(
timeout=httpx.Timeout(self.timeout / 1000, connect=self.timeout / 1000),
transport=RetryTransport()
)
return session

def prepare_request_headers(self, headers):
Expand Down
12 changes: 6 additions & 6 deletions src/yookassa/deal.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ def __init__(self):
self.client = ApiClient()

@classmethod
def find_one(cls, deal_id):
async def find_one(cls, deal_id):
"""
Get receipt information

Expand All @@ -26,11 +26,11 @@ def find_one(cls, deal_id):
raise ValueError('Invalid payment_id value')

path = instance.base_path + '/' + deal_id
response = instance.client.request(HttpVerb.GET, path)
response = await instance.client.request(HttpVerb.GET, path)
return DealResponse(response)

@classmethod
def create(cls, params, idempotency_key=None):
async def create(cls, params, idempotency_key=None):
"""
Create receipt

Expand All @@ -55,13 +55,13 @@ def create(cls, params, idempotency_key=None):
else:
raise TypeError('Invalid params value type')

response = instance.client.request(HttpVerb.POST, path, None, headers, params_object)
response = await instance.client.request(HttpVerb.POST, path, None, headers, params_object)
return DealResponse(response)

@classmethod
def list(cls, params):
async def list(cls, params):
instance = cls()
path = cls.base_path

response = instance.client.request(HttpVerb.GET, path, params)
response = await instance.client.request(HttpVerb.GET, path, params)
return DealListResponse(response)
20 changes: 10 additions & 10 deletions src/yookassa/payment.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ def __init__(self):
self.client = ApiClient()

@classmethod
def find_one(cls, payment_id):
async def find_one(cls, payment_id):
"""
Get information about payment

Expand All @@ -26,11 +26,11 @@ def find_one(cls, payment_id):
raise ValueError('Invalid payment_id value')

path = instance.base_path + '/' + payment_id
response = instance.client.request(HttpVerb.GET, path)
response = await instance.client.request(HttpVerb.GET, path)
return PaymentResponse(response)

@classmethod
def create(cls, params, idempotency_key=None):
async def create(cls, params, idempotency_key=None):
"""
Create payment

Expand All @@ -55,11 +55,11 @@ def create(cls, params, idempotency_key=None):
else:
raise TypeError('Invalid params value type')

response = instance.client.request(HttpVerb.POST, path, None, headers, params_object)
response = await instance.client.request(HttpVerb.POST, path, None, headers, params_object)
return PaymentResponse(response)

@classmethod
def capture(cls, payment_id, params=None, idempotency_key=None):
async def capture(cls, payment_id, params=None, idempotency_key=None):
"""
Capture payment

Expand Down Expand Up @@ -88,11 +88,11 @@ def capture(cls, payment_id, params=None, idempotency_key=None):
else:
params_object = None

response = instance.client.request(HttpVerb.POST, path, None, headers, params_object)
response = await instance.client.request(HttpVerb.POST, path, None, headers, params_object)
return PaymentResponse(response)

@classmethod
def cancel(cls, payment_id, idempotency_key=None):
async def cancel(cls, payment_id, idempotency_key=None):
"""
Cancel payment

Expand All @@ -111,13 +111,13 @@ def cancel(cls, payment_id, idempotency_key=None):
headers = {
'Idempotence-Key': str(idempotency_key)
}
response = instance.client.request(HttpVerb.POST, path, None, headers)
response = await instance.client.request(HttpVerb.POST, path, None, headers)
return PaymentResponse(response)

@classmethod
def list(cls, params):
async def list(cls, params):
instance = cls()
path = cls.base_path

response = instance.client.request(HttpVerb.GET, path, params)
response = await instance.client.request(HttpVerb.GET, path, params)
return PaymentListResponse(response)
8 changes: 4 additions & 4 deletions src/yookassa/payout.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ def __init__(self):
self.client = ApiClient()

@classmethod
def find_one(cls, payout_id):
async def find_one(cls, payout_id):
"""
Get receipt information

Expand All @@ -26,11 +26,11 @@ def find_one(cls, payout_id):
raise ValueError('Invalid payment_id value')

path = instance.base_path + '/' + payout_id
response = instance.client.request(HttpVerb.GET, path)
response = await instance.client.request(HttpVerb.GET, path)
return PayoutResponse(response)

@classmethod
def create(cls, params, idempotency_key=None):
async def create(cls, params, idempotency_key=None):
"""
Create receipt

Expand All @@ -55,5 +55,5 @@ def create(cls, params, idempotency_key=None):
else:
raise TypeError('Invalid params value type')

response = instance.client.request(HttpVerb.POST, path, None, headers, params_object)
response = await instance.client.request(HttpVerb.POST, path, None, headers, params_object)
return PayoutResponse(response)
12 changes: 6 additions & 6 deletions src/yookassa/receipt.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ def __init__(self):
self.client = ApiClient()

@classmethod
def find_one(cls, receipt_id):
async def find_one(cls, receipt_id):
"""
Get receipt information

Expand All @@ -27,11 +27,11 @@ def find_one(cls, receipt_id):
raise ValueError('Invalid payment_id value')

path = instance.base_path + '/' + receipt_id
response = instance.client.request(HttpVerb.GET, path)
response = await instance.client.request(HttpVerb.GET, path)
return ReceiptResponse(response)

@classmethod
def create(cls, params, idempotency_key=None):
async def create(cls, params, idempotency_key=None):
"""
Create receipt

Expand All @@ -56,13 +56,13 @@ def create(cls, params, idempotency_key=None):
else:
raise TypeError('Invalid params value type')

response = instance.client.request(HttpVerb.POST, path, None, headers, params_object)
response = await instance.client.request(HttpVerb.POST, path, None, headers, params_object)
return ReceiptResponse(response)

@classmethod
def list(cls, params):
async def list(cls, params):
instance = cls()
path = cls.base_path

response = instance.client.request(HttpVerb.GET, path, params)
response = await instance.client.request(HttpVerb.GET, path, params)
return ReceiptListResponse(response)
Loading