Skip to content

Commit

Permalink
fix: merge conflicts
Browse files Browse the repository at this point in the history
  • Loading branch information
ChogirmaliYigit committed Dec 13, 2023
2 parents 0778011 + 84649e4 commit e8c7ef6
Show file tree
Hide file tree
Showing 12 changed files with 458 additions and 86 deletions.
1 change: 1 addition & 0 deletions .pylintrc
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
[MASTER]
disable=no-member,
invalid-name,
unnecessary-pass,
useless-option-value,
too-few-public-methods,
Expand Down
22 changes: 14 additions & 8 deletions lib/payme/admin.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
from django.contrib import admin

from payme.models import CUSTOM_ORDER
from payme.models import Order as DefaultOrderModel

from payme.models import MerchantTransactionsModel

if not CUSTOM_ORDER:
admin.site.register(DefaultOrderModel)
from payme.models import (
FiscalData, MerchantTransactionsModel, PaymeItem,
PaymeOrder, ShippingDetail, OrderItem
)

admin.site.register(MerchantTransactionsModel)
admin.site.register(
[
MerchantTransactionsModel,
FiscalData,
PaymeItem,
PaymeOrder,
OrderItem,
ShippingDetail
]
)
7 changes: 7 additions & 0 deletions lib/payme/errors/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,3 +87,10 @@ class PaymeTimeoutException(Exception):
"""
Payme timeout exception that means that payme is working slowly.
"""


class QRCodeError(Exception):
"""
QRCodeError Exception \
Raises when an error occurs while generating a QR code.
"""
11 changes: 9 additions & 2 deletions lib/payme/methods/check_perform_transaction.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from payme.utils.get_params import get_params
from payme.models import PaymeOrder as Order
from payme.serializers import MerchantTransactionsModelSerializer
from payme.utils.get_params import clean_empty, get_params


class CheckPerformTransaction:
Expand All @@ -17,10 +18,16 @@ def __call__(self, params: dict) -> tuple:
)
serializer.is_valid(raise_exception=True)

order = Order.objects.get(
pk=serializer.validated_data.get('order_id')
)
detail = clean_empty(order.to_detail())

response = {
"result": {
"allow": True,
}
"detail": detail
}
}

return None, response
88 changes: 84 additions & 4 deletions lib/payme/methods/generate_link.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,18 @@
import base64
from decimal import Decimal
import json
import os
import typing
import uuid
from dataclasses import dataclass
from decimal import Decimal

import websocket
from websocket import WebSocketApp

from django.conf import settings

from payme.errors.exceptions import QRCodeError

PAYME_ID = settings.PAYME.get('PAYME_ID')
PAYME_ACCOUNT = settings.PAYME.get('PAYME_ACCOUNT')
PAYME_CALL_BACK_URL = settings.PAYME.get('PAYME_CALL_BACK_URL')
Expand Down Expand Up @@ -38,6 +47,11 @@ class GeneratePayLink:
def generate_link(self) -> str:
"""
GeneratePayLink for each order.
Full method documentation
----------
https://developer.help.paycom.uz/initsializatsiya-platezhey/otpravka-cheka-po-metodu-get
"""
generated_pay_link: str = "{payme_url}/{encode_params}"
params: str = 'm={payme_id};ac.{payme_account}={order_id};a={amount};c={call_back_url}'
Expand All @@ -60,14 +74,80 @@ def generate_link(self) -> str:
encode_params=str(encode_params, 'utf-8')
)

def __send_and_receive_data(self, data) -> typing.Union[str, None]:
# pylint: disable=missing-function-docstring

message = None

def on_message(ws: WebSocketApp, _message):
nonlocal message
message = _message

ws.close()

websocket.enableTrace(False)

ws = WebSocketApp(
url="wss://checkout.paycom.uz/",
keep_running=False,
on_message=on_message
)

ws.on_open = lambda ws: ws.send(json.dumps(data))
ws.run_forever(ping_interval=0.1)

return message

def to_qrcode(self, path: str = 'qr-codes', filename: str = None, **kwargs):
"""
Generate qr-code for order.
Full method documentation
----------
https://developer.help.paycom.uz/initsializatsiya-platezhey/generatsiya-knopki-oplaty-i-qr-koda
Parameters
----------
path: str -> output path (folder) name
filename: str -> output image name without suffix
lang: str -> user language. available values: ru, uz, en.
callback: str -> return url after payment or payment cancellation.
Returns
----------
str -> path of qr code svg
"""
data = {
"lang": kwargs.get("lang", "ru"),
"merchant": PAYME_ID,
"amount": self.amount,
"account": {PAYME_ACCOUNT: self.order_id},
"callback": kwargs.get("callback", PAYME_CALL_BACK_URL)
}
message = self.__send_and_receive_data(data)

if message is None:
raise QRCodeError

if not os.path.exists(path):
os.makedirs(path)

image_name = uuid.uuid4().hex if not filename else filename
image_output_path = f'{path}/{image_name}.svg'

with open(image_output_path, 'w', encoding='utf-8') as svg:
svg.write(message.split(',')[-1])

return image_output_path

@staticmethod
def to_tiyin(amount: Decimal) -> Decimal:
def to_tiyin(amount: int) -> int:
"""
Convert from sum to tiyin.
Parameters
----------
amount: Decimal -> order amount
amount: int -> order amount
"""
return amount * 100

Expand All @@ -78,6 +158,6 @@ def to_sum(amount: Decimal) -> Decimal:
Parameters
----------
amount: Decimal -> order amount
amount: int -> order amount
"""
return amount / 100
189 changes: 160 additions & 29 deletions lib/payme/migrations/0001_initial.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# pylint: disable=invalid-name
import django.db.models.deletion
from django.db import migrations, models


Expand All @@ -9,40 +10,170 @@ class Migration(migrations.Migration):

operations = [
migrations.CreateModel(
name='MerchantTransactionsModel',
name="FiscalData",
fields=[
('id', models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name='ID')
),
('_id', models.CharField(max_length=255, null=True)),
('transaction_id', models.CharField(max_length=255, null=True)),
('order_id', models.BigIntegerField(blank=True, null=True)),
('amount', models.FloatField(blank=True, null=True)),
('time', models.BigIntegerField(blank=True, null=True)),
('perform_time', models.BigIntegerField(default=0, null=True)),
('cancel_time', models.BigIntegerField(default=0, null=True)),
('state', models.IntegerField(default=1, null=True)),
('reason', models.CharField(blank=True, max_length=255, null=True)),
('created_at_ms', models.CharField(blank=True, max_length=255, null=True)),
('created_at', models.DateTimeField(auto_now_add=True)),
('updated_at', models.DateTimeField(auto_now=True)),
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("code", models.CharField(max_length=17)),
("units", models.IntegerField(blank=True, null=True)),
("package_code", models.CharField(max_length=255)),
("vat_percent", models.IntegerField(blank=True, default=0, null=True)),
],
options={
"verbose_name": "Fiscal Data",
"verbose_name_plural": "Fiscal Data",
},
),
migrations.CreateModel(
name='Order',
name="MerchantTransactionsModel",
fields=[
('id', models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name='ID')
),
('amount', models.IntegerField(blank=True, null=True)),
('created_at', models.DateTimeField(auto_now_add=True)),
('updated_at', models.DateTimeField(auto_now=True)),
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("_id", models.CharField(max_length=255, null=True)),
("transaction_id", models.CharField(max_length=255, null=True)),
("order_id", models.BigIntegerField(blank=True, null=True)),
("amount", models.BigIntegerField(blank=True, null=True)),
("time", models.BigIntegerField(blank=True, null=True)),
("perform_time", models.BigIntegerField(default=0, null=True)),
("cancel_time", models.BigIntegerField(default=0, null=True)),
("state", models.IntegerField(default=1, null=True)),
("reason", models.CharField(blank=True, max_length=255, null=True)),
(
"created_at_ms",
models.CharField(blank=True, max_length=255, null=True),
),
("created_at", models.DateTimeField(auto_now_add=True)),
("updated_at", models.DateTimeField(auto_now=True)),
],
options={
"verbose_name": "Merchant Transaction",
"verbose_name_plural": "Merchant Transactions",
},
),
migrations.CreateModel(
name="ShippingDetail",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("title", models.CharField(max_length=255)),
("price", models.BigIntegerField(default=0)),
],
options={
"verbose_name": "Shipping Detail",
"verbose_name_plural": "Shipping Details",
},
),
migrations.CreateModel(
name="PaymeOrder",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("receipt_type", models.IntegerField(default=0)),
(
"shipping",
models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.CASCADE,
to="payme.shippingdetail",
),
),
],
options={
"verbose_name": "Payme Order",
"verbose_name_plural": "Payme Orders",
},
),
migrations.CreateModel(
name="PaymeItem",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("discount", models.BigIntegerField(default=0)),
("title", models.CharField(max_length=255)),
("price", models.BigIntegerField(default=0)),
(
"fiscal_data",
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.SET_NULL,
to="payme.fiscaldata",
),
),
],
options={
"verbose_name": "Payme Item",
"verbose_name_plural": "Payme Items",
},
),
migrations.CreateModel(
name="OrderItem",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("count", models.IntegerField(default=1)),
(
"item",
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.SET_NULL,
to="payme.paymeitem",
),
),
(
"order",
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.SET_NULL,
to="payme.paymeorder",
),
),
],
options={
"verbose_name": "Payme Order Item",
"verbose_name_plural": "Payme Order Items",
},
),
]
Loading

0 comments on commit e8c7ef6

Please sign in to comment.