feat: billing guest access
This commit is contained in:
		
							
								
								
									
										3
									
								
								external/billing/__init__.py
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								external/billing/__init__.py
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
			
		||||
from .schemas import *
 | 
			
		||||
from .enums import *
 | 
			
		||||
from .billing_client import BillingClient
 | 
			
		||||
							
								
								
									
										27
									
								
								external/billing/billing_client.py
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								external/billing/billing_client.py
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,27 @@
 | 
			
		||||
import aiohttp
 | 
			
		||||
 | 
			
		||||
from .schemas import *
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class BillingClient:
 | 
			
		||||
    def __init__(self, api_key: str):
 | 
			
		||||
        self.api_key = api_key
 | 
			
		||||
        self.headers = {
 | 
			
		||||
            'Authorization': f'Bearer {self.api_key}'
 | 
			
		||||
        }
 | 
			
		||||
        self.base_url = 'https://billing.denco.store'
 | 
			
		||||
 | 
			
		||||
    async def _method(self, http_method, method, **kwargs):
 | 
			
		||||
        async with aiohttp.ClientSession(headers=self.headers) as session:
 | 
			
		||||
            async with session.request(http_method, self.base_url + method, **kwargs) as response:
 | 
			
		||||
                return await response.json()
 | 
			
		||||
 | 
			
		||||
    async def create(self, request: CreateBillRequestSchema) -> CreateBillingResponseSchema:
 | 
			
		||||
        json_data = request.model_dump()
 | 
			
		||||
        response = await self._method('POST', '/create', json=json_data)
 | 
			
		||||
        return CreateBillingResponseSchema.model_validate(response)
 | 
			
		||||
 | 
			
		||||
    async def notify_received(self, request: NotifyReceivedBillRequestSchema) -> NotifyReceivedBillResponseSchema:
 | 
			
		||||
        json_data = request.model_dump()
 | 
			
		||||
        response = await self._method('POST', '/notify-received', json=json_data)
 | 
			
		||||
        return NotifyReceivedBillResponseSchema.model_validate(response)
 | 
			
		||||
							
								
								
									
										6
									
								
								external/billing/enums.py
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								external/billing/enums.py
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,6 @@
 | 
			
		||||
from enum import StrEnum
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class NotificationChannel(StrEnum):
 | 
			
		||||
    PAYMENT_DETAILS = 'PAYMENT_DETAILS'
 | 
			
		||||
    PAYMENT_VERIFICATION = 'PAYMENT_VERIFICATION'
 | 
			
		||||
							
								
								
									
										81
									
								
								external/billing/schemas.py
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										81
									
								
								external/billing/schemas.py
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,81 @@
 | 
			
		||||
import re
 | 
			
		||||
from typing import List
 | 
			
		||||
 | 
			
		||||
from pydantic import field_validator
 | 
			
		||||
 | 
			
		||||
from schemas.base import BaseSchema
 | 
			
		||||
from .enums import NotificationChannel
 | 
			
		||||
from datetime import datetime as dt
 | 
			
		||||
from datetime import date
 | 
			
		||||
 | 
			
		||||
phone_regexp = re.compile(r'^((\+7)([0-9]){10})$')
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class CreateBillingRequestValue(BaseSchema):
 | 
			
		||||
    name: str = ""
 | 
			
		||||
    unit: str = "Руб"
 | 
			
		||||
    vat: str = "None"
 | 
			
		||||
 | 
			
		||||
    price: int
 | 
			
		||||
    amount: int = 1
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class CreateBillRequestItems(BaseSchema):
 | 
			
		||||
    values: List[CreateBillingRequestValue]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class CreateBillRequestSchema(BaseSchema):
 | 
			
		||||
    listener_transaction_id: int
 | 
			
		||||
    payer_name: str
 | 
			
		||||
    payer_inn: int
 | 
			
		||||
    payer_phone: str | None
 | 
			
		||||
    items: CreateBillRequestItems
 | 
			
		||||
 | 
			
		||||
    @field_validator("payer_phone", mode="before")
 | 
			
		||||
    def payer_phone_validator(cls, phone: str) -> str:
 | 
			
		||||
        if phone is None:
 | 
			
		||||
            return None
 | 
			
		||||
 | 
			
		||||
        if not phone.startswith("+"):
 | 
			
		||||
            phone = f"+{phone}"
 | 
			
		||||
 | 
			
		||||
        if phone_regexp.match(phone):
 | 
			
		||||
            return phone
 | 
			
		||||
 | 
			
		||||
        return None
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class NotifyReceivedBillRequestSchema(BaseSchema):
 | 
			
		||||
    listener_transaction_id: int
 | 
			
		||||
    channel: NotificationChannel
 | 
			
		||||
    received: bool
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class CreateBillingResponseSchema(BaseSchema):
 | 
			
		||||
    ok: bool
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class NotifyReceivedBillResponseSchema(BaseSchema):
 | 
			
		||||
    ok: bool
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class BillPaymentInfo(BaseSchema):
 | 
			
		||||
    pdf_url: str
 | 
			
		||||
    due_date: date
 | 
			
		||||
    payment_amount: int
 | 
			
		||||
    invoice_number: str
 | 
			
		||||
 | 
			
		||||
    @field_validator('due_date', mode='plain')
 | 
			
		||||
    def serialize_due_date(value: str) -> date:
 | 
			
		||||
        date = dt.strptime(value, '%Y-%m-%d').date()
 | 
			
		||||
        return date
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class BillPaymentStatus(BaseSchema):
 | 
			
		||||
    payed: bool
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class BillStatusUpdateRequest(BaseSchema):
 | 
			
		||||
    listener_transaction_id: int
 | 
			
		||||
    channel: NotificationChannel
 | 
			
		||||
    info: BillPaymentInfo | BillPaymentStatus
 | 
			
		||||
		Reference in New Issue
	
	Block a user