diff --git a/.github/workflows/pylint.yml b/.github/workflows/pylint.yml
new file mode 100644
index 0000000..4046520
--- /dev/null
+++ b/.github/workflows/pylint.yml
@@ -0,0 +1,24 @@
+name: Pylint
+
+on: [push]
+
+jobs:
+ build:
+ runs-on: ubuntu-latest
+ strategy:
+ matrix:
+ python-version: ["3.11"]
+ steps:
+ - uses: actions/checkout@v3
+ - name: Set up Python ${{ matrix.python-version }}
+ uses: actions/setup-python@v3
+ with:
+ python-version: ${{ matrix.python-version }}
+ - name: Install dependencies
+ run: |
+ python -m pip install --upgrade pip
+ pip install -r requirements/requirements.txt
+ pip install pylint
+ - name: Analysing the code with pylint
+ run: |
+ pylint ./lib/*
diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml
new file mode 100644
index 0000000..b05e9f6
--- /dev/null
+++ b/.github/workflows/release.yaml
@@ -0,0 +1,24 @@
+name: Release
+
+on:
+ release:
+ types:
+ - created
+
+jobs:
+ release:
+ name: "Publish release"
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: "actions/checkout@v3"
+ - uses: "actions/setup-python@v1"
+ with:
+ python-version: 3.8
+ - name: "Install dependencies"
+ run: "pip install -r requirements/dev-requirements.txt"
+ - name: "Publish to PyPI"
+ run: "./scripts/release.sh"
+ env:
+ TWINE_USERNAME: ${{ secrets.PYPI_USERNAME }}
+ TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }}
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..998cacb
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,10 @@
+core/
+db.sqlite3
+dist/
+venv/
+.vscode/
+.idea/
+__pycache__/
+paymentsuz.egg-info/
+payme_pkg.egg-info/
+manage.py
\ No newline at end of file
diff --git a/.pylintrc b/.pylintrc
new file mode 100644
index 0000000..70226f1
--- /dev/null
+++ b/.pylintrc
@@ -0,0 +1,6 @@
+[MASTER]
+disable=no-member,
+ unnecessary-pass,
+ useless-option-value,
+ too-few-public-methods,
+ missing-module-docstring
diff --git a/LICENSE.txt b/LICENSE.txt
new file mode 100644
index 0000000..aeb6397
--- /dev/null
+++ b/LICENSE.txt
@@ -0,0 +1,20 @@
+Copyright (c) 2021 Giorgos Myrianthous
+
+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.
\ No newline at end of file
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..a0685d4
--- /dev/null
+++ b/README.md
@@ -0,0 +1,893 @@
+# Payme Uzbekistan Integration Uzcard and Humo
+
+
+
+
+
+Support Group - Telegram
+YouTube - Watch Video
+Implementation Sample - https://github.com/PayTechUz/payme-sample
+
+## Installation
+
+```shell
+pip install payme-pkg
+```
+
+### Test-Credentials
+
+```
+Card Numer: 8600 4954 7331 6478 Expire Date: 03/99 SMS Code: 666666
+Card Numer: 8600 0691 9540 6311 Expire Date: 03/99 SMS Code: 666666
+```
+
+## Documentation
+
+- [Merchant API](#merchant-api)
+- [Generate Pay Link](#generate-pay-link)
+
+- Subscribe Cards
+
+ - [Cards Create](#cards-create)
+ - [Cards Get Verify Code](#cards-get-verify-code)
+ - [Cards Verify](#cards-verify)
+ - [Cards Check](#cards-check)
+ - [Cards Remove](#cards-remove)
+
+- Subscribe Receipts
+ - [Receipts Create](#receipts-create)
+ - [Receipts Pay](#receipts-pay)
+ - [Receipts Send](#receipts-send)
+ - [Receipts Cancel](#receipts-cancel)
+ - [Receipts Check](#receipts-check)
+ - [Receipts Get](#receipts-get)
+ - [Receipts Get All ](#receipts-get-all)
+
+# Merchant API
+
+## Installation to Django
+
+Add `'payme'` in to your settings.
+
+```python
+INSTALLED_APPS = [
+ ...
+ 'payme',
+ ...
+]
+```
+
+Add `'payme'` credentials inside to settings.
+
+```python
+PAYME: dict = {
+ 'PAYME_ID': 'payme-id',
+ 'PAYME_KEY': 'payme-key',
+ 'PAYME_URL': 'payme-checkout-url',
+ 'PAYME_CALL_BACK_URL': 'your-callback-url', # merchant api callback url
+ 'PAYME_MIN_AMOUNT': 'payme-min-amount', # integer field
+ 'PAYME_ACCOUNT': 'order-id',
+}
+
+ORDER_MODEL = 'your_app.models.Your_Order_Model'
+```
+
+Create a new View that about handling call backs
+```python
+from payme.views import MerchantAPIView
+
+
+class PaymeCallBackAPIView(MerchantAPIView):
+ def create_transaction(self, order_id, action, *args, **kwargs) -> None:
+ print(f"create_transaction for order_id: {order_id}, response: {action}")
+
+ def perform_transaction(self, order_id, action, *args, **kwargs) -> None:
+ print(f"perform_transaction for order_id: {order_id}, response: {action}")
+
+ def cancel_transaction(self, order_id, action, *args, **kwargs) -> None:
+ print(f"cancel_transaction for order_id: {order_id}, response: {action}")
+```
+
+Add a `payme` path to core of urlpatterns:
+
+```python
+from django.urls import path
+from django.urls import include
+
+from your_app.views import PaymeCallBackAPIView
+
+urlpatterns = [
+ ...
+ path("payments/merchant/", PaymeCallBackAPIView.as_view()),
+ ...
+]
+```
+
+Run migrations
+
+```shell
+python manage.py migrate
+```
+
+🎉 Congratulations you have been integrated merchant api methods with django, keep reading docs. After successfull migrations check your admin panel and see results what happened.
+
+## Generate Pay Link
+
+Example to generate link:
+
+- Input
+
+```python
+from pprint import pprint
+
+from payme.methods.generate_link import GeneratePayLink
+
+pay_link = GeneratePayLink(
+ order_id=999,
+ amount=9999
+).generate_link()
+
+pprint(pay_link)
+```
+
+- Output
+
+```
+Link: https://checkout.paycom.uz/bT01ZTczMGU4ZTBiODUyYTQxN2FhNDljZWI7YWMub3JkZXItaWQ9OTk5O2E9OTk5OTtjPXlvdXItY2FsbGJhY2stdXJs
+```
+
+## Cards Create
+
+Example for cards create method for to generate token from card:
+
+- Request
+
+```python
+from pprint import pprint
+
+from payme.cards.subscribe_cards import PaymeSubscribeCards
+
+client = PaymeSubscribeCards(
+ base_url="https://checkout.test.paycom.uz/api/",
+ paycom_id=$paycom_id
+)
+
+resp = client.cards_create(
+ number="8600069195406311",
+ expire="0399",
+ save=True
+)
+
+pprint(resp)
+```
+
+- Response
+
+```json
+{
+ "jsonrpc": "2.0",
+ "result": {
+ "card": {
+ "number": "860006******6311",
+ "expire": "03/99",
+ "token": "63119784d15d8d8d093b37b8_ADHrAykwnAIc2hm4hPPriktZ8nnuvR96S9Kzmjb3Fcix25IrJmMKrGxP9VUEP9rRDKRhtYjUw0vsXON7PYEyMCHtDKpMuM4krrIk8jdnyK7bXkSBSCyiGs2aahIrep6TSodIAxqutMJ4g3O8FZ8vC1DSMKzOaX0UF8fDKNexXV039Qnj4bNQc6NcpKGJn0wUX8d0RBqkmKid4WyUQnT987ZQDM2mT2IGNZtugvN4tDJTXBVTpqCWkXnZ0YWj64Ye0ztr91Mibtndo0Y1s5nCA6wufUZZugJ6c7rse19XNFSSieFM7AWi9VqybMe4eeWiZEBriAbFhrf8kQvrpBmwUEp05GjvFMgH0ku3vyUtSuJI36exHheXuJK66KstcX1i69EaF3",
+ "recurrent": true,
+ "verify": false,
+ "type": "22618"
+ }
+ }
+}
+```
+
+## Cards Get Verify Code
+
+Example for cards get verify:
+
+- Request
+
+```python
+from pprint import pprint
+
+from payme.cards.subscribe_cards import PaymeSubscribeCards
+
+
+client = PaymeSubscribeCards(
+ base_url="https://checkout.test.paycom.uz/api/",
+ paycom_id=$paycom_id
+)
+
+resp = client.card_get_verify_code(
+ token="630e5ffdd15d8d8d093b379b_2fsaoABWafecn20kofV4PFafFZjeGDWS9adM1PmboQaEZbbaxMcnaskctMbU9Iv8qgrOuKGz8SnjvZvYXDK64m1eS9gA5jZ7BBRaQybMXrDPtFPJ1fwek5B1KoIv5cMiCWYXj7ezpYEdJAKTIQw0Np9HsTXjqco4gQG3m8MOfeH9ovkdm66O6yj45oKXRmJyAK5i0SchXNNomACH3Oq80KyoRE1VoBRxvoKyMkOx0xcepXovxK9d3v26a8z7UtyokwY33N8MupviM3A5WHB5Xh35WZJJyFnxTSi1vvnYnG7uVd6Bb1GjV2yAHnimss8aEZGW5V7ZiPrhf8r6WJAeHciYDGK3msRKZJBQTfjgOdE9tGrEnMezVkxr1JXX0xSn5qqec2"
+)
+
+pprint(resp)
+```
+
+- Response
+
+```json
+{
+ "jsonrpc": "2.0",
+ "result": {
+ "sent": true,
+ "phone": "99890*****66",
+ "wait": 60000
+ }
+}
+```
+
+## Cards Verify
+
+Example for cards verify method:
+
+- Request
+
+```python
+from pprint import pprint
+
+from payme.cards.subscribe_cards import PaymeSubscribeCards
+
+
+client = PaymeSubscribeCards(
+ base_url="https://checkout.test.paycom.uz/api/",
+ paycom_id=$paycom_id
+)
+
+resp = client.cards_verify(
+ verify_code="666666",
+ token="630e691fd15d8d8d093b379c_70mKyzqS8d1wTWzovIGjt9dKmjpn1KI8Y9XakPrfpbUASTBaZYbC1DjDcjYRmuNJep9gZrTRtHyEGBQYmBaPufuozF51bv4qEPsQnodq1VcD7tYyREwUXjMXXZUeu7Ek0REQCekCvVHX6rtNBpb4vtViJoNVjp94XpTqu0Bn3yYYb0CHu951wFydzRsieGxjGNrvx1oKyBcq0CdOUwoffRIt2VPvx5R2aVmc6ahwyhn387FEEcpO1PnjIJkWKTBWdI35ZPQnb1u1oss5aPg06E279THXRkoTThixbeqiD2JkWSXweNVGGDhTS30V4j61G3NWEPO2H3k4uFmCjjIQSzx4TxKzUgHg1i2q953PRUGjT4JZBRHMDxaN5tWuctEMNmY06p"
+)
+
+pprint(resp)
+```
+
+- Response
+
+```json
+{
+ "jsonrpc": "2.0",
+ "result": {
+ "card": {
+ "number": "860006******6311",
+ "expire": "03/99",
+ "token": "63118a5dd15d8d8d093b37b7_X2j34OIJPnROfsgzYZCZ0w7OcC50zzwiowTsotEVO1uUbxkzaDrvdOno6jicQTrcRmxvibxrye4vUS3AynTNPaPCTGpfk3RCKmT9NaOAyyTmctAjWsjwvqGR5XUzAP1Xcx12GkhuQi6VJ4BeaIXOokSRu06rRjaivmJQ8HTiJiR9b3OmZtrhkIRNcNXnnp9zYm1mFP4BuqGpS8BMnY0ASIE6ffxWykjgBcDTAfWBFt4mg7O9Dsvx0aj3IB8z3RIbZYtDZJnUVhCZrwW7ONVI9uEAdxNthorjO6PbV7TQ8XCjrztgGf6uCtOwwxasiIUVZN6tCVDk8A8NvVSUzUHXQHVkaPn5heJNa3K4WsffIckq7SwMbiw3UbawipeZKyD3iwk1Km",
+ "recurrent": true,
+ "verify": true,
+ "type": "22618"
+ }
+ }
+}
+```
+
+## Cards Check
+
+Example for cards check:
+
+- Request
+
+```python
+from pprint import pprint
+
+from payme.cards.subscribe_cards import PaymeSubscribeCards
+
+
+client = PaymeSubscribeCards(
+ base_url="https://checkout.test.paycom.uz/api/",
+ paycom_id=$paycom_id
+)
+
+resp = client.cards_check(
+ token="630e691fd15d8d8d093b379c_70mKyzqS8d1wTWzovIGjt9dKmjpn1KI8Y9XakPrfpbUASTBaZYbC1DjDcjYRmuNJep9gZrTRtHyEGBQYmBaPufuozF51bv4qEPsQnodq1VcD7tYyREwUXjMXXZUeu7Ek0REQCekCvVHX6rtNBpb4vtViJoNVjp94XpTqu0Bn3yYYb0CHu951wFydzRsieGxjGNrvx1oKyBcq0CdOUwoffRIt2VPvx5R2aVmc6ahwyhn387FEEcpO1PnjIJkWKTBWdI35ZPQnb1u1oss5aPg06E279THXRkoTThixbeqiD2JkWSXweNVGGDhTS30V4j61G3NWEPO2H3k4uFmCjjIQSzx4TxKzUgHg1i2q953PRUGjT4JZBRHMDxaN5tWuctEMNmY06p"
+)
+
+pprint(resp)
+```
+
+- Response
+
+```json
+{
+ "jsonrpc": "2.0",
+ "result": {
+ "card": {
+ "number": "860006******6311",
+ "expire": "03/99",
+ "token": "63119b36d15d8d8d093b37c1_IJtHxZ46h5viyo8RIJCmQyE8qBw6PUWUdFKTMCVWrPoMMi4kJYsKyVdjQrIx6a12jDfEPVhhEqWm94FYvYh7IEjIs4xn0n3mM8Quw5dhd6ZT0dOK6u1spqWRMIDBpDMhHj2Ga8zZMAfeoiDAcrWScXS1AP2tkQHcJ40rBzHGHS6DoVeIheF70c0wO1kVQG0G5hDWguSGf2ZRFcBtpabv5BQkqSchxWKdCSVPIGiS6X7eF8YStdz1aGPzFyjDbaKT0vXNUMbQ7gaKh4PeQbruVVwFDfeIWqGeNmgCCPU4X0wCHFjTt8K61e9VOauNeU81ckoKHD8XGzCwGFJHrC4sHvNv4no3RifWhHCQF9GmFKf8cP2qh4pqTKwu3gOITaX5Ss71tC",
+ "recurrent": true,
+ "verify": true,
+ "type": "22618"
+ }
+ }
+}
+```
+
+## Cards Remove
+
+Example for cards create method for to generate token from card:
+
+- Request
+
+```python
+from pprint import pprint
+
+from payme.cards.subscribe_cards import PaymeSubscribeCards
+
+
+client = PaymeSubscribeCards(
+ base_url="https://checkout.test.paycom.uz/api/",
+ paycom_id=$paycom_id
+)
+
+resp = client.cards_remove(
+ token="630e691fd15d8d8d093b379c_70mKyzqS8d1wTWzovIGjt9dKmjpn1KI8Y9XakPrfpbUASTBaZYbC1DjDcjYRmuNJep9gZrTRtHyEGBQYmBaPufuozF51bv4qEPsQnodq1VcD7tYyREwUXjMXXZUeu7Ek0REQCekCvVHX6rtNBpb4vtViJoNVjp94XpTqu0Bn3yYYb0CHu951wFydzRsieGxjGNrvx1oKyBcq0CdOUwoffRIt2VPvx5R2aVmc6ahwyhn387FEEcpO1PnjIJkWKTBWdI35ZPQnb1u1oss5aPg06E279THXRkoTThixbeqiD2JkWSXweNVGGDhTS30V4j61G3NWEPO2H3k4uFmCjjIQSzx4TxKzUgHg1i2q953PRUGjT4JZBRHMDxaN5tWuctEMNmY06p"
+)
+
+pprint(resp)
+```
+
+- Response
+
+```json
+{
+ "jsonrpc": "2.0",
+ "result": {
+ "success": true
+ }
+}
+```
+
+## Receipts Create
+
+Example for receipts create method:
+
+- Request
+
+```python
+from pprint import pprint
+
+from payme.receipts.subscribe_receipts import PaymeSubscribeReceipts
+
+
+rclient = PaymeSubscribeReceipts(
+ base_url="https://checkout.test.paycom.uz/api/",
+ paycom_id=$paycom_id,
+ paycom_key=$paycom_key
+)
+
+resp = rclient.receipts_create(
+ amount=10000,
+ order_id="1"
+)
+
+pprint(resp)
+```
+
+- Response
+
+```json
+{
+ "jsonrpc": "2.0",
+ "result": {
+ "receipt": {
+ "_id": "63119becc4420cbf2712a24c",
+ "create_time": 1662098412270,
+ "pay_time": 0,
+ "cancel_time": 0,
+ "state": 0,
+ "type": 2,
+ "external": false,
+ "operation": -1,
+ "category": null,
+ "error": null,
+ "description": "",
+ "detail": null,
+ "amount": 400000,
+ "currency": 860,
+ "commission": 0,
+ "account": [
+ {
+ "name": "transaction",
+ "title": "Номер чека",
+ "value": "2326",
+ "main": true
+ }
+ ],
+ "card": null,
+ "merchant": {
+ "_id": "5e730e8e0b852a417aa49ceb",
+ "name": "test",
+ "organization": "ЧП «test test»",
+ "address": "",
+ "business_id": "5e730e740b852a417aa49cea",
+ "epos": {
+ "merchantId": "106600000050000",
+ "terminalId": "20660000"
+ },
+ "date": 1584598670296,
+ "logo": null,
+ "type": "Internet",
+ "terms": null
+ },
+ "meta": {
+ "source": "subscribe",
+ "owner": "5e730e8e0b852a417aa49ceb"
+ },
+ "processing_id": null
+ }
+ }
+}
+```
+
+## Receipts Pay
+
+Example for receipts pay method:
+
+- Request
+
+```python
+from pprint import pprint
+
+from payme.receipts.subscribe_receipts import PaymeSubscribeReceipts
+
+
+rclient = PaymeSubscribeReceipts(
+ base_url="https://checkout.test.paycom.uz/api/",
+ paycom_id=$paycom_id,
+ paycom_key=$paycom_key
+)
+
+resp = rclient.receipts_pay(
+ invoice_id="631186b6c4420cbf2712a243",
+ token="63118a5dd15d8d8d093b37b7_X2j34OIJPnROfsgzYZCZ0w7OcC50zzwiowTsotEVO1uUbxkzaDrvdOno6jicQTrcRmxvibxrye4vUS3AynTNPaPCTGpfk3RCKmT9NaOAyyTmctAjWsjwvqGR5XUzAP1Xcx12GkhuQi6VJ4BeaIXOokSRu06rRjaivmJQ8HTiJiR9b3OmZtrhkIRNcNXnnp9zYm1mFP4BuqGpS8BMnY0ASIE6ffxWykjgBcDTAfWBFt4mg7O9Dsvx0aj3IB8z3RIbZYtDZJnUVhCZrwW7ONVI9uEAdxNthorjO6PbV7TQ8XCjrztgGf6uCtOwwxasiIUVZN6tCVDk8A8NvVSUzUHXQHVkaPn5heJNa3K4WsffIckq7SwMbiw3UbawipeZKyD3iwk1Km",
+ phone="998901304527"
+)
+
+pprint(resp)
+```
+
+- Response
+
+```json
+{
+ "jsonrpc": "2.0",
+ "id": 123,
+ "result": {
+ "receipt": {
+ "_id": "63119becc4420cbf2712a24c",
+ "create_time": 1662098438706,
+ "pay_time": 1662098438804,
+ "cancel_time": 0,
+ "state": 4,
+ "type": 2,
+ "external": false,
+ "operation": -1,
+ "category": null,
+ "error": null,
+ "description": "",
+ "detail": null,
+ "amount": 400000,
+ "currency": 860,
+ "commission": 0,
+ "account": [
+ {
+ "name": "transaction",
+ "title": "Номер чека",
+ "value": "2326",
+ "main": true
+ }
+ ],
+ "card": {
+ "number": "860006******6311",
+ "expire": "9903"
+ },
+ "merchant": {
+ "_id": "5e730e8e0b852a417aa49ceb",
+ "name": "test",
+ "organization": "ЧП «test test»",
+ "address": "",
+ "business_id": "5e730e740b852a417aa49cea",
+ "epos": {
+ "merchantId": "106600000050000",
+ "terminalId": "20660000"
+ },
+ "date": 1584598670296,
+ "logo": null,
+ "type": "Internet",
+ "terms": null
+ },
+ "meta": {
+ "source": "subscribe",
+ "owner": "5e730e8e0b852a417aa49ceb"
+ },
+ "processing_id": 0
+ }
+ }
+}
+```
+
+## Receipts Send
+
+Example for receipts send method:
+
+- Request
+
+```python
+from pprint import pprint
+
+from payme.receipts.subscribe_receipts import PaymeSubscribeReceipts
+
+
+rclient = PaymeSubscribeReceipts(
+ base_url="https://checkout.test.paycom.uz/api/",
+ paycom_id=$paycom_id,
+ paycom_key=$paycom_key
+)
+
+resp = rclient.receipts_send(
+ invoice_id="631186b6c4420cbf2712a243",
+ phone="998901304527"
+)
+
+pprint(resp)
+```
+
+- Response
+
+```json
+{
+ "jsonrpc": "2.0",
+ "id": 123,
+ "result": {
+ "success": true
+ }
+}
+```
+
+## Receipts Cancel
+
+Example for receipts cancel method:
+
+- Request
+
+```python
+from pprint import pprint
+
+from payme.receipts.subscribe_receipts import PaymeSubscribeReceipts
+
+
+rclient = PaymeSubscribeReceipts(
+ base_url="https://checkout.test.paycom.uz/api/",
+ paycom_id=$paycom_id,
+ paycom_key=$paycom_key
+)
+
+resp = rclient.receipts_cancel(
+ invoice_id="63119303c4420cbf2712a245"
+)
+
+pprint(resp)
+```
+
+- Response
+
+```json
+{
+ "jsonrpc": "2.0",
+ "id": 123,
+ "result": {
+ "receipt": {
+ "_id": "63119becc4420cbf2712a24c",
+ "create_time": 1662098438706,
+ "pay_time": 1662098438804,
+ "cancel_time": 0,
+ "state": 21,
+ "type": 2,
+ "external": false,
+ "operation": -1,
+ "category": null,
+ "error": null,
+ "description": "",
+ "detail": null,
+ "amount": 400000,
+ "currency": 860,
+ "commission": 0,
+ "account": [
+ {
+ "name": "transaction",
+ "title": "Номер чека",
+ "value": "2326",
+ "main": true
+ }
+ ],
+ "card": {
+ "number": "860006******6311",
+ "expire": "9903"
+ },
+ "merchant": {
+ "_id": "5e730e8e0b852a417aa49ceb",
+ "name": "test",
+ "organization": "ЧП «test test»",
+ "address": "",
+ "business_id": "5e730e740b852a417aa49cea",
+ "epos": {
+ "merchantId": "106600000050000",
+ "terminalId": "20660000"
+ },
+ "date": 1584598670296,
+ "logo": null,
+ "type": "Internet",
+ "terms": null
+ },
+ "meta": {
+ "source": "subscribe",
+ "owner": "5e730e8e0b852a417aa49ceb",
+ "source_cancel": "subscribe"
+ },
+ "processing_id": null
+ }
+ }
+}
+```
+
+## Receipts Check
+
+Example for receipts check method:
+
+- Request
+
+```python
+from pprint import pprint
+
+from payme.receipts.subscribe_receipts import PaymeSubscribeReceipts
+
+
+rclient = PaymeSubscribeReceipts(
+ base_url="https://checkout.test.paycom.uz/api/",
+ paycom_id=$paycom_id,
+ paycom_key=$paycom_key
+)
+
+resp = rclient.receipts_check(
+ invoice_id="63119303c4420cbf2712a245"
+)
+
+pprint(resp)
+```
+
+- Response
+
+```json
+{
+ "jsonrpc": "2.0",
+ "id": 123,
+ "result": {
+ "state": 0
+ }
+}
+```
+
+## Receipts Get
+
+Example for receipts get method:
+
+- Request
+
+```python
+from pprint import pprint
+
+from payme.receipts.subscribe_receipts import PaymeSubscribeReceipts
+
+
+rclient = PaymeSubscribeReceipts(
+ base_url="https://checkout.test.paycom.uz/api/",
+ paycom_id=$paycom_id,
+ paycom_key=$paycom_key
+)
+
+resp = rclient.reciepts_get(
+ invoice_id="6311946bc4420cbf2712a247"
+)
+
+pprint(resp)
+```
+
+- Response
+
+```json
+{
+ "jsonrpc": "2.0",
+ "id": 123,
+ "result": {
+ "receipt": {
+ "_id": "6311946bc4420cbf2712a247",
+ "create_time": 1662096491076,
+ "pay_time": 0,
+ "cancel_time": 0,
+ "state": 0,
+ "type": 2,
+ "external": false,
+ "operation": -1,
+ "category": null,
+ "error": null,
+ "description": "",
+ "detail": null,
+ "amount": 400000,
+ "currency": 860,
+ "commission": 0,
+ "account": [
+ {
+ "name": "transaction",
+ "title": "Номер чека",
+ "value": "2325",
+ "main": true
+ }
+ ],
+ "card": null,
+ "merchant": {
+ "_id": "5e730e8e0b852a417aa49ceb",
+ "name": "test",
+ "organization": "ЧП «test test»",
+ "address": "",
+ "business_id": "5e730e740b852a417aa49cea",
+ "epos": {
+ "merchantId": "106600000050000",
+ "terminalId": "20660000"
+ },
+ "date": 1584598670296,
+ "logo": null,
+ "type": "Internet",
+ "terms": null
+ },
+ "meta": {
+ "source": "subscribe",
+ "owner": "5e730e8e0b852a417aa49ceb"
+ },
+ "processing_id": null
+ }
+ }
+}
+```
+
+## Receipts Get All
+
+Example for receipts get all method:
+
+- Request
+
+```python
+from pprint import pprint
+
+from payme.receipts.subscribe_receipts import PaymeSubscribeReceipts
+
+
+rclient = PaymeSubscribeReceipts(
+ base_url="https://checkout.test.paycom.uz/api/",
+ paycom_id=$paycom_id,
+ paycom_key=$paycom_key
+)
+
+resp = rclient.reciepts_get_all(
+ count=2,
+ _from=1636398000000,
+ to=1636398000000,
+ offset=0
+)
+
+pprint(resp)
+```
+
+- Response
+
+```json
+{
+ "jsonrpc": "2.0",
+ "id": 123,
+ "result": [
+ {
+ "_id": "6311946bc4420cbf2712a247",
+ "create_time": 1662096491076,
+ "pay_time": 0,
+ "cancel_time": 0,
+ "state": 0,
+ "type": 2,
+ "external": false,
+ "operation": -1,
+ "category": null,
+ "error": null,
+ "description": "",
+ "detail": null,
+ "amount": 400000,
+ "currency": 860,
+ "commission": 0,
+ "account": [
+ {
+ "name": "transaction",
+ "title": {
+ "ru": "Номер чека",
+ "uz": "Chek raqami"
+ },
+ "value": 2325,
+ "main": true
+ }
+ ],
+ "card": null,
+ "merchant": {
+ "_id": "5e730e8e0b852a417aa49ceb",
+ "name": "test",
+ "organization": "ЧП «test test»",
+ "address": "",
+ "business_id": "5e730e740b852a417aa49cea",
+ "epos": {
+ "merchantId": "106600000050000",
+ "terminalId": "20660000"
+ },
+ "date": 1584598670296,
+ "logo": null,
+ "type": {
+ "ru": "Internet",
+ "uz": "Internet"
+ },
+ "terms": null
+ },
+ "meta": {
+ "source": "subscribe",
+ "owner": "5e730e8e0b852a417aa49ceb"
+ },
+ "processing_id": null
+ },
+ {
+ "_id": "63119303c4420cbf2712a245",
+ "create_time": 1662096131667,
+ "pay_time": 0,
+ "cancel_time": 1662096182979,
+ "state": 50,
+ "type": 2,
+ "external": false,
+ "operation": -1,
+ "category": null,
+ "error": null,
+ "description": "",
+ "detail": null,
+ "amount": 400000,
+ "currency": 860,
+ "commission": 0,
+ "account": [
+ {
+ "name": "transaction",
+ "title": {
+ "ru": "Номер чека",
+ "uz": "Chek raqami"
+ },
+ "value": 2324,
+ "main": true
+ }
+ ],
+ "card": null,
+ "merchant": {
+ "_id": "5e730e8e0b852a417aa49ceb",
+ "name": "test",
+ "organization": "ЧП «test test»",
+ "address": "",
+ "business_id": "5e730e740b852a417aa49cea",
+ "epos": {
+ "merchantId": "106600000050000",
+ "terminalId": "20660000"
+ },
+ "date": 1584598670296,
+ "logo": null,
+ "type": {
+ "ru": "Internet",
+ "uz": "Internet"
+ },
+ "terms": null
+ },
+ "meta": {
+ "source": "subscribe",
+ "owner": "5e730e8e0b852a417aa49ceb",
+ "source_cancel": "subscribe"
+ },
+ "processing_id": null
+ }
+ ]
+}
+```
diff --git a/docs/collections/postman/paytechuz-payme_postman.json b/docs/collections/postman/paytechuz-payme_postman.json
new file mode 100644
index 0000000..4154905
--- /dev/null
+++ b/docs/collections/postman/paytechuz-payme_postman.json
@@ -0,0 +1,928 @@
+{
+ "info": {
+ "_postman_id": "7a2b3ba8-d989-415f-b26a-cdbce1d52d01",
+ "name": "paytechuz-payme",
+ "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json",
+ "description": ""
+ },
+ "item": [
+ {
+ "name": "Merchant-API",
+ "item": [
+ {
+ "name": "create-transaction",
+ "request": {
+ "method": "POST",
+ "url": {
+ "raw": "http://localhost:8000/payments/merchant/",
+ "path": [
+ "payments",
+ "merchant"
+ ],
+ "protocol": "http",
+ "host": [
+ "localhost"
+ ],
+ "port": "8000"
+ },
+ "header": [
+ {
+ "key": "AUTHORIZATION",
+ "value": "Basic XXX"
+ },
+ {
+ "key": "Accept",
+ "value": "*/*",
+ "disabled": true
+ },
+ {
+ "key": "User-Agent",
+ "value": "Thunder Client (https://www.thunderclient.com)",
+ "disabled": true
+ }
+ ],
+ "body": {
+ "mode": "raw",
+ "options": {
+ "raw": {
+ "language": "json"
+ }
+ },
+ "raw": "{\n \"jsonrpc\": \"2.0\",\n \"method\": \"CreateTransaction\",\n \"params\": {\n \"account\": {\n \"order_id\": \"4\"\n },\n \"amount\": 100,\n \"id\": \"64266c93432361b4e0342bdd\",\n \"time\": 1680239763901\n }\n}\n"
+ }
+ }
+ },
+ {
+ "name": "incorrect-order",
+ "request": {
+ "method": "POST",
+ "url": {
+ "raw": "http://localhost:8000/payments/merchant/",
+ "path": [
+ "payments",
+ "merchant"
+ ],
+ "protocol": "http",
+ "host": [
+ "localhost"
+ ],
+ "port": "8000"
+ },
+ "header": [
+ {
+ "key": "AUTHORIZATION",
+ "value": "Basic XXX"
+ },
+ {
+ "key": "Accept",
+ "value": "*/*",
+ "disabled": true
+ },
+ {
+ "key": "User-Agent",
+ "value": "Thunder Client (https://www.thunderclient.com)",
+ "disabled": true
+ }
+ ],
+ "body": {
+ "mode": "raw",
+ "options": {
+ "raw": {
+ "language": "json"
+ }
+ },
+ "raw": "{\n \"jsonrpc\": \"2.0\",\n \"id\": 67828,\n \"method\": \"CheckPerformTransaction\",\n \"params\": {\n \"amount\": 999999999,\n \"account\": {\n \"order_id\": \"999999999\"\n }\n }\n}\n"
+ }
+ }
+ },
+ {
+ "name": "check-transaction",
+ "request": {
+ "method": "POST",
+ "url": {
+ "raw": "http://localhost:8000/payments/merchant/",
+ "path": [
+ "payments",
+ "merchant"
+ ],
+ "protocol": "http",
+ "host": [
+ "localhost"
+ ],
+ "port": "8000"
+ },
+ "header": [
+ {
+ "key": "AUTHORIZATION",
+ "value": "Basic XXX"
+ },
+ {
+ "key": "Accept",
+ "value": "*/*",
+ "disabled": true
+ },
+ {
+ "key": "User-Agent",
+ "value": "Thunder Client (https://www.thunderclient.com)",
+ "disabled": true
+ }
+ ],
+ "body": {
+ "mode": "raw",
+ "options": {
+ "raw": {
+ "language": "json"
+ }
+ },
+ "raw": "{\n \"jsonrpc\": \"2.0\",\n \"method\": \"CheckTransaction\",\n \"params\": {\n \"id\": \"6346454fc67a522e0887022b\"\n }\n}\n"
+ }
+ }
+ },
+ {
+ "name": "incorrect-auth",
+ "request": {
+ "method": "POST",
+ "url": {
+ "raw": "http://localhost:8000/payments/merchant/?AUTHORIZATION=Basic XXX",
+ "query": [
+ {
+ "key": "AUTHORIZATION",
+ "value": "Basic XXX"
+ }
+ ],
+ "variable": [],
+ "path": [
+ "payments",
+ "merchant"
+ ],
+ "protocol": "http",
+ "host": [
+ "localhost"
+ ],
+ "port": "8000"
+ },
+ "header": [
+ {
+ "key": "Accept",
+ "value": "*/*",
+ "disabled": true
+ },
+ {
+ "key": "User-Agent",
+ "value": "Thunder Client (https://www.thunderclient.com)",
+ "disabled": true
+ }
+ ],
+ "auth": {
+ "type": "noauth"
+ }
+ }
+ },
+ {
+ "name": "perform-transaction ",
+ "request": {
+ "method": "POST",
+ "url": {
+ "raw": "http://localhost:8000/payments/merchant/",
+ "path": [
+ "payments",
+ "merchant"
+ ],
+ "protocol": "http",
+ "host": [
+ "localhost"
+ ],
+ "port": "8000"
+ },
+ "header": [
+ {
+ "key": "AUTHORIZATION",
+ "value": "Basic XXX"
+ },
+ {
+ "key": "Accept",
+ "value": "*/*",
+ "disabled": true
+ },
+ {
+ "key": "User-Agent",
+ "value": "Thunder Client (https://www.thunderclient.com)",
+ "disabled": true
+ }
+ ],
+ "body": {
+ "mode": "raw",
+ "options": {
+ "raw": {
+ "language": "json"
+ }
+ },
+ "raw": "{\n \"jsonrpc\": \"2.0\",\n \"method\": \"CancelTransaction\",\n \"params\": {\n \"id\": \"64266c93432361b4e0342bdd\",\n \"reason\": 5\n }\n}"
+ }
+ }
+ },
+ {
+ "name": "check-perform-transaction",
+ "request": {
+ "method": "POST",
+ "url": {
+ "raw": "http://localhost:8000/payments/merchant/",
+ "path": [
+ "payments",
+ "merchant"
+ ],
+ "protocol": "http",
+ "host": [
+ "localhost"
+ ],
+ "port": "8000"
+ },
+ "header": [
+ {
+ "key": "AUTHORIZATION",
+ "value": "Basic XXX"
+ },
+ {
+ "key": "Accept",
+ "value": "*/*",
+ "disabled": true
+ },
+ {
+ "key": "User-Agent",
+ "value": "Thunder Client (https://www.thunderclient.com)",
+ "disabled": true
+ }
+ ],
+ "body": {
+ "mode": "raw",
+ "options": {
+ "raw": {
+ "language": "json"
+ }
+ },
+ "raw": "{\n \"jsonrpc\": \"2.0\",\n \"method\": \"CheckPerformTransaction\",\n \"params\": {\n \"amount\": 100,\n \"account\": {\n \"order_id\": \"3\"\n }\n }\n}"
+ }
+ }
+ },
+ {
+ "name": "cancel-transaction",
+ "request": {
+ "method": "POST",
+ "url": {
+ "raw": "http://localhost:8000/payments/merchant/",
+ "path": [
+ "payments",
+ "merchant"
+ ],
+ "protocol": "http",
+ "host": [
+ "localhost"
+ ],
+ "port": "8000"
+ },
+ "header": [
+ {
+ "key": "AUTHORIZATION",
+ "value": "Basic XXX"
+ },
+ {
+ "key": "Accept",
+ "value": "*/*",
+ "disabled": true
+ },
+ {
+ "key": "User-Agent",
+ "value": "Thunder Client (https://www.thunderclient.com)",
+ "disabled": true
+ }
+ ],
+ "body": {
+ "mode": "raw",
+ "options": {
+ "raw": {
+ "language": "json"
+ }
+ },
+ "raw": "{\n \"jsonrpc\": \"2.0\",\n \"method\": \"CheckPerformTransaction\",\n \"params\": {\n \"amount\": 100,\n \"account\": {\n \"order_id\": \"3\"\n }\n }\n}"
+ }
+ }
+ },
+ {
+ "name": "get-statement",
+ "request": {
+ "method": "POST",
+ "url": {
+ "raw": "http://localhost:8000/payments/merchant/",
+ "path": [
+ "payments",
+ "merchant"
+ ],
+ "protocol": "http",
+ "host": [
+ "localhost"
+ ],
+ "port": "8000"
+ },
+ "header": [
+ {
+ "key": "AUTHORIZATION",
+ "value": "Basic XXX"
+ },
+ {
+ "key": "Accept",
+ "value": "*/*",
+ "disabled": true
+ },
+ {
+ "key": "User-Agent",
+ "value": "Thunder Client (https://www.thunderclient.com)",
+ "disabled": true
+ }
+ ],
+ "body": {
+ "mode": "raw",
+ "options": {
+ "raw": {
+ "language": "json"
+ }
+ },
+ "raw": "{\n \"method\" : \"GetStatement\",\n \"params\" : {\n \"from\" : 1666462755066,\n \"to\" : 1690672447727\n }\n}"
+ }
+ }
+ }
+ ]
+ },
+ {
+ "name": "cards_create",
+ "request": {
+ "method": "POST",
+ "url": {
+ "raw": "https://checkout.test.paycom.uz/api/",
+ "path": [
+ "api"
+ ],
+ "protocol": "https",
+ "host": [
+ "checkout",
+ "test",
+ "paycom",
+ "uz"
+ ]
+ },
+ "header": [
+ {
+ "key": "X-Auth",
+ "value": "5e730e8e0b852a417aa49ceb"
+ },
+ {
+ "key": "Accept",
+ "value": "*/*",
+ "disabled": true
+ },
+ {
+ "key": "User-Agent",
+ "value": "Thunder Client (https://www.thunderclient.com)",
+ "disabled": true
+ }
+ ],
+ "body": {
+ "mode": "raw",
+ "options": {
+ "raw": {
+ "language": "json"
+ }
+ },
+ "raw": "{\n \"id\": \"paytechuz\",\n \"method\": \"cards.create\",\n \"params\": {\"card\": {\"number\": \"8600495473316478\",\"expire\": \"0399\"},\n \"save\": true\n }\n}"
+ }
+ }
+ },
+ {
+ "name": "cards_get_veriy_code",
+ "request": {
+ "method": "POST",
+ "url": {
+ "raw": "https://checkout.test.paycom.uz/api/",
+ "path": [
+ "api"
+ ],
+ "protocol": "https",
+ "host": [
+ "checkout",
+ "test",
+ "paycom",
+ "uz"
+ ]
+ },
+ "header": [
+ {
+ "key": "X-Auth",
+ "value": "$payme_id"
+ },
+ {
+ "key": "Accept",
+ "value": "*/*",
+ "disabled": true
+ },
+ {
+ "key": "User-Agent",
+ "value": "Thunder Client (https://www.thunderclient.com)",
+ "disabled": true
+ }
+ ],
+ "body": {
+ "mode": "raw",
+ "options": {
+ "raw": {
+ "language": "json"
+ }
+ },
+ "raw": "{\n \"id\": \"paytechyz\",\n \"method\": \"cards.get_verify_code\",\n \"params\": {\n \"token\": \"63468a065a046a41490e664e_GQdx3ewoSpAIUieZ55EVBT9o3XauKiITgDjIzMhdsTBho8ctGV8sKXE7M47uyNMSGt4b9hMvcKMssNvs74UV03J7TZ6QIHfR5z8regqQjaS58x0ABm91TNpH07rd7TGxsoHN4WEs1iIr2W9MUUHCAyZePsBmcuYfvbOBbfeV4xcXh9kTsPEwV768KjEjtCjokNeER1i0pbJrnCoGoRyAr37ZaYsu28IOBQzzzGCThoVxIn3uM6pQFeW1xuDKD5cMRk9tQNc2zJWaoHQ6eHTR7EadOkUEJXIYgyeYBXkiYBN1pW58Msb89Kt4tMDhJKanCwQbBo4eiUdxWtI8xRfksXdgGDjqvCNKrsciw5MSrDdcRqupo61WvXD0d4IianWyTEfS5p\"\n }\n}"
+ }
+ }
+ },
+ {
+ "name": "cards_verify",
+ "request": {
+ "method": "POST",
+ "url": {
+ "raw": "https://checkout.test.paycom.uz/api/",
+ "path": [
+ "api"
+ ],
+ "protocol": "https",
+ "host": [
+ "checkout",
+ "test",
+ "paycom",
+ "uz"
+ ]
+ },
+ "header": [
+ {
+ "key": "X-Auth",
+ "value": "$payme_id"
+ },
+ {
+ "key": "Accept",
+ "value": "*/*",
+ "disabled": true
+ },
+ {
+ "key": "User-Agent",
+ "value": "Thunder Client (https://www.thunderclient.com)",
+ "disabled": true
+ }
+ ],
+ "body": {
+ "mode": "raw",
+ "options": {
+ "raw": {
+ "language": "json"
+ }
+ },
+ "raw": "{\n \"id\": \"paytechuz\",\n \"method\": \"cards.verify\",\n \"params\": {\n \"token\": \"63317a19d15d8d8d093b3b73_sF6OYNgJ5zXd2BXNpEZgDZJQVyPnaVAQY7ziO6nDx11ZyX67gCTQxspvWN2ZMGaWfKG8YuKsgoRecgN3IrnYhQxubavr7Z8zreOAXF4GRJW8M2gNfF4RnCu2cYCYzQ2dIRRvp3uS5b2B48aVsyQGwo0v3tQqNAdOfYskgiwbChNObvo4TnzewRYaGZbpqfEiN78anY03EMShjU6mRh0YouIRENr4VCXd4eBAoAVWAas8ZikYHYh0aTBFMproAKx2Pf2ZYuiBsyO2f2cTYpuu1kRciHJZ2ZEN5TRupJKgg06pwxBK5pu5dsOXomQWNGCvOetsahOPmX0nU25E5cEfGHfRDMIUWOjbR2MbginPdP9BXS50Q2Q1DOQO0pHSmf9nRvXKTm\",\n \"code\": \"666666\"\n }\n}"
+ }
+ }
+ },
+ {
+ "name": "cards_remove",
+ "request": {
+ "method": "POST",
+ "url": {
+ "raw": "https://checkout.test.paycom.uz/api/",
+ "path": [
+ "api"
+ ],
+ "protocol": "https",
+ "host": [
+ "checkout",
+ "test",
+ "paycom",
+ "uz"
+ ]
+ },
+ "header": [
+ {
+ "key": "X-Auth",
+ "value": "$payme_id"
+ },
+ {
+ "key": "Accept",
+ "value": "*/*",
+ "disabled": true
+ },
+ {
+ "key": "User-Agent",
+ "value": "Thunder Client (https://www.thunderclient.com)",
+ "disabled": true
+ }
+ ],
+ "body": {
+ "mode": "raw",
+ "options": {
+ "raw": {
+ "language": "json"
+ }
+ },
+ "raw": "{\n \"id\": \"paytechuz\",\n \"method\": \"cards.remove\",\n \"params\": {\n \"token\": \"63119afed15d8d8d093b37bf_FZKC9EDMu7Ke7wPvEoYpMgyA1wFDWynDewB9AQSkYk6ic2isbQdYatJuVN1GknSmhEwftPxVZ1wZPw6TzJc4BYqWRmPyV3eyqJz4cK9D91aEkZ5TNBkMnhxxgXefDryHGYdpSqUuMV914QwpcA5e8cB5yqIaCp8P6W8FBeY6vKcNIfSSBaDniMZfsKV9vSyroqupKWfYcPHig2m5KyN5aBWU12f5yBtpOt6IRwbXoDre3BBVMfTKrXesQfghcrs4bUgOmcPoNDGXh8nxEkucFSNmc5EymAZZ56hSnXpYgtv4QhGxNiX3tSsk6raRMWstJNqMBb4vQABs54Zd8IohboSAGZW3M87CRiVmQEDKwvrC8y4aaNmfV33q03EppQnaJArZDx\"\n }\n}"
+ }
+ }
+ },
+ {
+ "name": "cards_check",
+ "request": {
+ "method": "POST",
+ "url": {
+ "raw": "https://checkout.test.paycom.uz/api/",
+ "path": [
+ "api"
+ ],
+ "protocol": "https",
+ "host": [
+ "checkout",
+ "test",
+ "paycom",
+ "uz"
+ ]
+ },
+ "header": [
+ {
+ "key": "X-Auth",
+ "value": "$payme_id"
+ },
+ {
+ "key": "Accept",
+ "value": "*/*",
+ "disabled": true
+ },
+ {
+ "key": "User-Agent",
+ "value": "Thunder Client (https://www.thunderclient.com)",
+ "disabled": true
+ }
+ ],
+ "body": {
+ "mode": "raw",
+ "options": {
+ "raw": {
+ "language": "json"
+ }
+ },
+ "raw": "{\n \"id\": 123,\n \"method\": \"cards.check\",\n \"params\": {\n \"token\": \"6321688682dcb3b90def1ff5_JMry9v8Ko0SAT8D5HGHZfCxi5RFHIudX9adt6ZqWD3uQgy9VTYGovP9ceIoXOq4KjPe9pyCm33cfGAUJ2WZgrThXRqnNzYrzvKo34fyH3UrEde9kaeqtk79sz4ZN3RNXHn6PwknEqONVi9yhS0Uv16OgY7wsiIfCZufayiwfYAKevCngcprYsZrJNpnheUjS56hnFyaRMR4KaPnEXCJXZkdxuiICk2m8BipM5hYhmfopQImik4j5GOZucTmUj3Ez3vGzwrwM3Z4sEBpmBJpaiaIahbncCosCEG11RDqHWj9jWOJrR3ipc7i0xCHM2zRIq1ICG9nO78rZvQ9v1FRQAuef0fUODQUmcOYcGAuKsdfKFrBwo5rxEHKTVpzuZDGN2zMS5J\"\n }\n}"
+ }
+ }
+ },
+ {
+ "name": "receipts_create",
+ "request": {
+ "method": "POST",
+ "url": {
+ "raw": "https://checkout.test.paycom.uz/api/",
+ "path": [
+ "api"
+ ],
+ "protocol": "https",
+ "host": [
+ "checkout",
+ "test",
+ "paycom",
+ "uz"
+ ]
+ },
+ "header": [
+ {
+ "key": "X-Auth",
+ "value": "$payme_id"
+ },
+ {
+ "key": "Accept",
+ "value": "*/*",
+ "disabled": true
+ },
+ {
+ "key": "User-Agent",
+ "value": "Thunder Client (https://www.thunderclient.com)",
+ "disabled": true
+ }
+ ],
+ "body": {
+ "mode": "raw",
+ "options": {
+ "raw": {
+ "language": "json"
+ }
+ },
+ "raw": "{\n \"id\": \"paytechuz\",\n \"method\": \"receipts.create\",\n \"params\": {\n \"amount\": 400000,\n \"account\": {\n \"order_id\": 106\n }\n }\n}"
+ }
+ }
+ },
+ {
+ "name": "receipts_pay",
+ "request": {
+ "method": "POST",
+ "url": {
+ "raw": "https://checkout.test.paycom.uz/api/",
+ "path": [
+ "api"
+ ],
+ "protocol": "https",
+ "host": [
+ "checkout",
+ "test",
+ "paycom",
+ "uz"
+ ]
+ },
+ "header": [
+ {
+ "key": "X-Auth",
+ "value": "$payme_id:$payme_key"
+ },
+ {
+ "key": "Accept",
+ "value": "*/*",
+ "disabled": true
+ },
+ {
+ "key": "User-Agent",
+ "value": "Thunder Client (https://www.thunderclient.com)",
+ "disabled": true
+ }
+ ],
+ "body": {
+ "mode": "raw",
+ "options": {
+ "raw": {
+ "language": "json"
+ }
+ },
+ "raw": "{\n \"id\": \"paytechuz\",\n \"method\": \"receipts.pay\",\n \"params\": {\n \"id\": \"63119becc4420cbf2712a24c\",\n \"token\": \"64232286890565aa4e37c2b0_TnOzC2HkPKJu6ndDeHKdyR4cQU6aIvauqqVqKmmmMFMrNTH0sByAQuPpOUTaPswth0Bxj9VKYDUNsgBhRIgIQydvH8C1iyca0wJING9kNvFemDEWUUutbBW5e1Fjh8VxYNak7Qm6Yac1tty6qgDxHnTfFMzfw5Svrq3fM8RjCr5F7IDgySRi02CJiXyNwCZxnhZtgmmimhApsXDySxyFjW1hDERh2hvZYEZMWyohnX6yaadKpOFv0QiOSWYyrMXPa1HfMmpFFaiCzjX6eOBFJJZhuJJsGxqxxgQBeuRBUOtnSAnrmzxj8j1sOEAMnIISjpZo3wABui2h7KpwIEWg9cmsuRHzYiw3NZFPKmWu5Q7WAYXDcuCBx7X5XwtJFIdUo559iN\",\n \"payer\": {\n \"phone\": \"998901304527\"\n }\n }\n}"
+ }
+ }
+ },
+ {
+ "name": "receipts_send",
+ "request": {
+ "method": "POST",
+ "url": {
+ "raw": "https://checkout.test.paycom.uz/api/",
+ "path": [
+ "api"
+ ],
+ "protocol": "https",
+ "host": [
+ "checkout",
+ "test",
+ "paycom",
+ "uz"
+ ]
+ },
+ "header": [
+ {
+ "key": "X-Auth",
+ "value": "$payme_id:$payme_key"
+ },
+ {
+ "key": "Accept",
+ "value": "*/*",
+ "disabled": true
+ },
+ {
+ "key": "User-Agent",
+ "value": "Thunder Client (https://www.thunderclient.com)",
+ "disabled": true
+ }
+ ],
+ "body": {
+ "mode": "raw",
+ "options": {
+ "raw": {
+ "language": "json"
+ }
+ },
+ "raw": "{\n \"id\": \"paytechuz\",\n \"method\": \"receipts.send\",\n \"params\": {\n \"id\": \"63119becc4420cbf2712a24c\",\n \"phone\": \"998901304527\"\n }\n}"
+ }
+ }
+ },
+ {
+ "name": "receipts_cancel",
+ "request": {
+ "method": "POST",
+ "url": {
+ "raw": "https://checkout.test.paycom.uz/api/",
+ "path": [
+ "api"
+ ],
+ "protocol": "https",
+ "host": [
+ "checkout",
+ "test",
+ "paycom",
+ "uz"
+ ]
+ },
+ "header": [
+ {
+ "key": "X-Auth",
+ "value": "$payme_id:$payme_key"
+ },
+ {
+ "key": "Accept",
+ "value": "*/*",
+ "disabled": true
+ },
+ {
+ "key": "User-Agent",
+ "value": "Thunder Client (https://www.thunderclient.com)",
+ "disabled": true
+ }
+ ],
+ "body": {
+ "mode": "raw",
+ "options": {
+ "raw": {
+ "language": "json"
+ }
+ },
+ "raw": "{\n \"id\": \"paytechuz\",\n \"method\": \"receipts.cancel\",\n \"params\": {\n \"id\": \"63119becc4420cbf2712a24c\"\n }\n}"
+ }
+ }
+ },
+ {
+ "name": "receipts_check",
+ "request": {
+ "method": "POST",
+ "url": {
+ "raw": "https://checkout.test.paycom.uz/api/",
+ "path": [
+ "api"
+ ],
+ "protocol": "https",
+ "host": [
+ "checkout",
+ "test",
+ "paycom",
+ "uz"
+ ]
+ },
+ "header": [
+ {
+ "key": "X-Auth",
+ "value": "$payme_id:$payme_key"
+ },
+ {
+ "key": "Accept",
+ "value": "*/*",
+ "disabled": true
+ },
+ {
+ "key": "User-Agent",
+ "value": "Thunder Client (https://www.thunderclient.com)",
+ "disabled": true
+ }
+ ],
+ "body": {
+ "mode": "raw",
+ "options": {
+ "raw": {
+ "language": "json"
+ }
+ },
+ "raw": "{\n \"id\": \"paytechuz\",\n \"method\": \"receipts.check\",\n \"params\": {\n \"id\": \"635aa3295f103c97ef1c7606\"\n }\n}"
+ }
+ }
+ },
+ {
+ "name": "reciepts_get",
+ "request": {
+ "method": "POST",
+ "url": {
+ "raw": "https://checkout.test.paycom.uz/api/",
+ "path": [
+ "api"
+ ],
+ "protocol": "https",
+ "host": [
+ "checkout",
+ "test",
+ "paycom",
+ "uz"
+ ]
+ },
+ "header": [
+ {
+ "key": "X-Auth",
+ "value": "$payme_id:$payme_key"
+ },
+ {
+ "key": "Accept",
+ "value": "*/*",
+ "disabled": true
+ },
+ {
+ "key": "User-Agent",
+ "value": "Thunder Client (https://www.thunderclient.com)",
+ "disabled": true
+ }
+ ],
+ "body": {
+ "mode": "raw",
+ "options": {
+ "raw": {
+ "language": "json"
+ }
+ },
+ "raw": "{\n \"id\": \"paytechuz\",\n \"method\": \"receipts.get\",\n \"params\": {\n \"id\": \"6311946bc4420cbf2712a247\"\n }\n}"
+ }
+ }
+ },
+ {
+ "name": "reciepts_get_all",
+ "request": {
+ "method": "POST",
+ "url": {
+ "raw": "https://checkout.test.paycom.uz/api/",
+ "path": [
+ "api"
+ ],
+ "protocol": "https",
+ "host": [
+ "checkout",
+ "test",
+ "paycom",
+ "uz"
+ ]
+ },
+ "header": [
+ {
+ "key": "X-Auth",
+ "value": "$payme_id:$payme_key"
+ },
+ {
+ "key": "Accept",
+ "value": "*/*",
+ "disabled": true
+ },
+ {
+ "key": "User-Agent",
+ "value": "Thunder Client (https://www.thunderclient.com)",
+ "disabled": true
+ }
+ ],
+ "body": {
+ "mode": "raw",
+ "options": {
+ "raw": {
+ "language": "json"
+ }
+ },
+ "raw": "{\n \"id\": \"paytechuz\",\n \"method\": \"receipts.get_all\",\n \"params\": {\n \"count\": 2,\n \"from\": 1612640000,\n \"to\": 1612726400,\n \"offset\": 0\n }\n}"
+ }
+ }
+ },
+ {
+ "name": "get_fiskal_data",
+ "request": {
+ "method": "POST",
+ "url": {
+ "raw": "https://checkout.test.paycom.uz/api/",
+ "path": [
+ "api"
+ ],
+ "protocol": "https",
+ "host": [
+ "checkout",
+ "test",
+ "paycom",
+ "uz"
+ ]
+ },
+ "header": [
+ {
+ "key": "X-Auth",
+ "value": "$payme_id:$payme_key"
+ },
+ {
+ "key": "Accept",
+ "value": "*/*",
+ "disabled": true
+ },
+ {
+ "key": "User-Agent",
+ "value": "Thunder Client (https://www.thunderclient.com)",
+ "disabled": true
+ }
+ ],
+ "body": {
+ "mode": "raw",
+ "options": {
+ "raw": {
+ "language": "json"
+ }
+ },
+ "raw": "{\n \"id\": \"paytechuz\",\n \"method\": \"receipts.set_fiscal_data\",\n \"params\": {\n \"id\": 1,\n \"fiscal_data\": {\n \"status_code\": 1,\n \"message\": 1,\n \"terminal_id\": 1,\n \"receipt_id\": 1,\n \"date\": 1,\n \"fiscal_sign\": 1,\n \"qr_code_url\": 1\n }\n }\n}"
+ }
+ }
+ }
+ ]
+}
\ No newline at end of file
diff --git a/docs/collections/thunder/paytechuz-payme_thunder.json b/docs/collections/thunder/paytechuz-payme_thunder.json
new file mode 100644
index 0000000..c93cd1a
--- /dev/null
+++ b/docs/collections/thunder/paytechuz-payme_thunder.json
@@ -0,0 +1,741 @@
+{
+ "client": "Thunder Client",
+ "collectionName": "paytechuz-payme",
+ "dateExported": "2023-08-04T06:43:15.236Z",
+ "version": "1.1",
+ "folders": [
+ {
+ "_id": "41aa7417-7725-4863-9baa-b3fa3e069fc6",
+ "name": "Merchant-API",
+ "containerId": "",
+ "created": "2023-08-04T06:35:53.675Z",
+ "sortNum": 10000,
+ "settings": {}
+ }
+ ],
+ "requests": [
+ {
+ "_id": "ada2fbab-a260-41f0-b689-505d3c531edd",
+ "colId": "aa8793c8-dbc4-44d0-844a-fe6a53e53f61",
+ "containerId": "41aa7417-7725-4863-9baa-b3fa3e069fc6",
+ "name": "create-transaction",
+ "url": "http://localhost:8000/payments/merchant/",
+ "method": "POST",
+ "sortNum": 10000,
+ "created": "2023-08-04T06:35:53.676Z",
+ "modified": "2023-08-04T06:40:26.964Z",
+ "headers": [
+ {
+ "name": "AUTHORIZATION",
+ "value": "Basic XXX"
+ },
+ {
+ "name": "Accept",
+ "value": "*/*",
+ "isDisabled": true
+ },
+ {
+ "name": "User-Agent",
+ "value": "Thunder Client (https://www.thunderclient.com)",
+ "isDisabled": true
+ }
+ ],
+ "params": [],
+ "body": {
+ "type": "json",
+ "raw": "{\n \"jsonrpc\": \"2.0\",\n \"method\": \"CreateTransaction\",\n \"params\": {\n \"account\": {\n \"order_id\": \"4\"\n },\n \"amount\": 100,\n \"id\": \"64266c93432361b4e0342bdd\",\n \"time\": 1680239763901\n }\n}\n",
+ "form": []
+ },
+ "tests": []
+ },
+ {
+ "_id": "05282e20-e6cb-45a2-8810-aa896d0a64a8",
+ "colId": "aa8793c8-dbc4-44d0-844a-fe6a53e53f61",
+ "containerId": "41aa7417-7725-4863-9baa-b3fa3e069fc6",
+ "name": "incorrect-order",
+ "url": "http://localhost:8000/payments/merchant/",
+ "method": "POST",
+ "sortNum": 15000,
+ "created": "2023-08-04T06:35:53.677Z",
+ "modified": "2023-08-04T06:40:19.588Z",
+ "headers": [
+ {
+ "name": "AUTHORIZATION",
+ "value": "Basic XXX"
+ },
+ {
+ "name": "Accept",
+ "value": "*/*",
+ "isDisabled": true
+ },
+ {
+ "name": "User-Agent",
+ "value": "Thunder Client (https://www.thunderclient.com)",
+ "isDisabled": true
+ }
+ ],
+ "params": [],
+ "body": {
+ "type": "json",
+ "raw": "{\n \"jsonrpc\": \"2.0\",\n \"id\": 67828,\n \"method\": \"CheckPerformTransaction\",\n \"params\": {\n \"amount\": 999999999,\n \"account\": {\n \"order_id\": \"999999999\"\n }\n }\n}\n",
+ "form": []
+ },
+ "tests": []
+ },
+ {
+ "_id": "032d6b97-ed12-410e-82ab-b580b343238a",
+ "colId": "aa8793c8-dbc4-44d0-844a-fe6a53e53f61",
+ "containerId": "41aa7417-7725-4863-9baa-b3fa3e069fc6",
+ "name": "check-transaction",
+ "url": "http://localhost:8000/payments/merchant/",
+ "method": "POST",
+ "sortNum": 20000,
+ "created": "2023-08-04T06:35:53.678Z",
+ "modified": "2023-08-04T06:40:45.730Z",
+ "headers": [
+ {
+ "name": "AUTHORIZATION",
+ "value": "Basic XXX"
+ },
+ {
+ "name": "Accept",
+ "value": "*/*",
+ "isDisabled": true
+ },
+ {
+ "name": "User-Agent",
+ "value": "Thunder Client (https://www.thunderclient.com)",
+ "isDisabled": true
+ }
+ ],
+ "params": [],
+ "body": {
+ "type": "json",
+ "raw": "{\n \"jsonrpc\": \"2.0\",\n \"method\": \"CheckTransaction\",\n \"params\": {\n \"id\": \"6346454fc67a522e0887022b\"\n }\n}\n",
+ "form": []
+ },
+ "tests": []
+ },
+ {
+ "_id": "9e8fe1f2-b827-41a4-98e1-428227ae7379",
+ "colId": "aa8793c8-dbc4-44d0-844a-fe6a53e53f61",
+ "containerId": "41aa7417-7725-4863-9baa-b3fa3e069fc6",
+ "name": "incorrect-auth",
+ "url": "http://localhost:8000/payments/merchant/?AUTHORIZATION=Basic XXX",
+ "method": "POST",
+ "sortNum": 30000,
+ "created": "2023-08-04T06:35:53.679Z",
+ "modified": "2023-08-04T06:35:53.679Z",
+ "headers": [
+ {
+ "name": "Accept",
+ "value": "*/*",
+ "isDisabled": true
+ },
+ {
+ "name": "User-Agent",
+ "value": "Thunder Client (https://www.thunderclient.com)",
+ "isDisabled": true
+ }
+ ],
+ "params": [
+ {
+ "name": "AUTHORIZATION",
+ "value": "Basic XXX",
+ "isPath": false
+ }
+ ],
+ "auth": {
+ "type": "none"
+ },
+ "tests": []
+ },
+ {
+ "_id": "316f7d8f-d77e-45bd-9679-1e35de792616",
+ "colId": "aa8793c8-dbc4-44d0-844a-fe6a53e53f61",
+ "containerId": "41aa7417-7725-4863-9baa-b3fa3e069fc6",
+ "name": "perform-transaction ",
+ "url": "http://localhost:8000/payments/merchant/",
+ "method": "POST",
+ "sortNum": 40000,
+ "created": "2023-08-04T06:35:53.680Z",
+ "modified": "2023-08-04T06:41:04.798Z",
+ "headers": [
+ {
+ "name": "AUTHORIZATION",
+ "value": "Basic XXX"
+ },
+ {
+ "name": "Accept",
+ "value": "*/*",
+ "isDisabled": true
+ },
+ {
+ "name": "User-Agent",
+ "value": "Thunder Client (https://www.thunderclient.com)",
+ "isDisabled": true
+ }
+ ],
+ "params": [],
+ "body": {
+ "type": "json",
+ "raw": "{\n \"jsonrpc\": \"2.0\",\n \"method\": \"CancelTransaction\",\n \"params\": {\n \"id\": \"64266c93432361b4e0342bdd\",\n \"reason\": 5\n }\n}",
+ "form": []
+ },
+ "tests": []
+ },
+ {
+ "_id": "245e1fca-4f9f-4c1f-855f-f8dff59be4dd",
+ "colId": "aa8793c8-dbc4-44d0-844a-fe6a53e53f61",
+ "containerId": "",
+ "name": "cards_create",
+ "url": "https://checkout.test.paycom.uz/api/",
+ "method": "POST",
+ "sortNum": 50000,
+ "created": "2023-08-04T06:35:53.681Z",
+ "modified": "2023-08-04T06:35:53.681Z",
+ "headers": [
+ {
+ "name": "X-Auth",
+ "value": "5e730e8e0b852a417aa49ceb"
+ },
+ {
+ "name": "Accept",
+ "value": "*/*",
+ "isDisabled": true
+ },
+ {
+ "name": "User-Agent",
+ "value": "Thunder Client (https://www.thunderclient.com)",
+ "isDisabled": true
+ }
+ ],
+ "params": [],
+ "body": {
+ "type": "json",
+ "raw": "{\n \"id\": \"paytechuz\",\n \"method\": \"cards.create\",\n \"params\": {\"card\": {\"number\": \"8600495473316478\",\"expire\": \"0399\"},\n \"save\": true\n }\n}",
+ "form": []
+ },
+ "tests": []
+ },
+ {
+ "_id": "7c2ec61a-233f-4575-abec-773671505179",
+ "colId": "aa8793c8-dbc4-44d0-844a-fe6a53e53f61",
+ "containerId": "",
+ "name": "cards_get_veriy_code",
+ "url": "https://checkout.test.paycom.uz/api/",
+ "method": "POST",
+ "sortNum": 60000,
+ "created": "2023-08-04T06:35:53.682Z",
+ "modified": "2023-08-04T06:37:20.662Z",
+ "headers": [
+ {
+ "name": "X-Auth",
+ "value": "$payme_id"
+ },
+ {
+ "name": "Accept",
+ "value": "*/*",
+ "isDisabled": true
+ },
+ {
+ "name": "User-Agent",
+ "value": "Thunder Client (https://www.thunderclient.com)",
+ "isDisabled": true
+ }
+ ],
+ "params": [],
+ "body": {
+ "type": "json",
+ "raw": "{\n \"id\": \"paytechyz\",\n \"method\": \"cards.get_verify_code\",\n \"params\": {\n \"token\": \"63468a065a046a41490e664e_GQdx3ewoSpAIUieZ55EVBT9o3XauKiITgDjIzMhdsTBho8ctGV8sKXE7M47uyNMSGt4b9hMvcKMssNvs74UV03J7TZ6QIHfR5z8regqQjaS58x0ABm91TNpH07rd7TGxsoHN4WEs1iIr2W9MUUHCAyZePsBmcuYfvbOBbfeV4xcXh9kTsPEwV768KjEjtCjokNeER1i0pbJrnCoGoRyAr37ZaYsu28IOBQzzzGCThoVxIn3uM6pQFeW1xuDKD5cMRk9tQNc2zJWaoHQ6eHTR7EadOkUEJXIYgyeYBXkiYBN1pW58Msb89Kt4tMDhJKanCwQbBo4eiUdxWtI8xRfksXdgGDjqvCNKrsciw5MSrDdcRqupo61WvXD0d4IianWyTEfS5p\"\n }\n}",
+ "form": []
+ },
+ "tests": []
+ },
+ {
+ "_id": "0d4a3e29-573a-4efb-b859-4e844ec2fdb3",
+ "colId": "aa8793c8-dbc4-44d0-844a-fe6a53e53f61",
+ "containerId": "",
+ "name": "cards_verify",
+ "url": "https://checkout.test.paycom.uz/api/",
+ "method": "POST",
+ "sortNum": 70000,
+ "created": "2023-08-04T06:35:53.683Z",
+ "modified": "2023-08-04T06:37:31.620Z",
+ "headers": [
+ {
+ "name": "X-Auth",
+ "value": "$payme_id"
+ },
+ {
+ "name": "Accept",
+ "value": "*/*",
+ "isDisabled": true
+ },
+ {
+ "name": "User-Agent",
+ "value": "Thunder Client (https://www.thunderclient.com)",
+ "isDisabled": true
+ }
+ ],
+ "params": [],
+ "body": {
+ "type": "json",
+ "raw": "{\n \"id\": \"paytechuz\",\n \"method\": \"cards.verify\",\n \"params\": {\n \"token\": \"63317a19d15d8d8d093b3b73_sF6OYNgJ5zXd2BXNpEZgDZJQVyPnaVAQY7ziO6nDx11ZyX67gCTQxspvWN2ZMGaWfKG8YuKsgoRecgN3IrnYhQxubavr7Z8zreOAXF4GRJW8M2gNfF4RnCu2cYCYzQ2dIRRvp3uS5b2B48aVsyQGwo0v3tQqNAdOfYskgiwbChNObvo4TnzewRYaGZbpqfEiN78anY03EMShjU6mRh0YouIRENr4VCXd4eBAoAVWAas8ZikYHYh0aTBFMproAKx2Pf2ZYuiBsyO2f2cTYpuu1kRciHJZ2ZEN5TRupJKgg06pwxBK5pu5dsOXomQWNGCvOetsahOPmX0nU25E5cEfGHfRDMIUWOjbR2MbginPdP9BXS50Q2Q1DOQO0pHSmf9nRvXKTm\",\n \"code\": \"666666\"\n }\n}",
+ "form": []
+ },
+ "tests": []
+ },
+ {
+ "_id": "1422768f-ccf2-4585-91cb-c6d83bfb2a17",
+ "colId": "aa8793c8-dbc4-44d0-844a-fe6a53e53f61",
+ "containerId": "",
+ "name": "cards_remove",
+ "url": "https://checkout.test.paycom.uz/api/",
+ "method": "POST",
+ "sortNum": 80000,
+ "created": "2023-08-04T06:35:53.684Z",
+ "modified": "2023-08-04T06:37:40.613Z",
+ "headers": [
+ {
+ "name": "X-Auth",
+ "value": "$payme_id"
+ },
+ {
+ "name": "Accept",
+ "value": "*/*",
+ "isDisabled": true
+ },
+ {
+ "name": "User-Agent",
+ "value": "Thunder Client (https://www.thunderclient.com)",
+ "isDisabled": true
+ }
+ ],
+ "params": [],
+ "body": {
+ "type": "json",
+ "raw": "{\n \"id\": \"paytechuz\",\n \"method\": \"cards.remove\",\n \"params\": {\n \"token\": \"63119afed15d8d8d093b37bf_FZKC9EDMu7Ke7wPvEoYpMgyA1wFDWynDewB9AQSkYk6ic2isbQdYatJuVN1GknSmhEwftPxVZ1wZPw6TzJc4BYqWRmPyV3eyqJz4cK9D91aEkZ5TNBkMnhxxgXefDryHGYdpSqUuMV914QwpcA5e8cB5yqIaCp8P6W8FBeY6vKcNIfSSBaDniMZfsKV9vSyroqupKWfYcPHig2m5KyN5aBWU12f5yBtpOt6IRwbXoDre3BBVMfTKrXesQfghcrs4bUgOmcPoNDGXh8nxEkucFSNmc5EymAZZ56hSnXpYgtv4QhGxNiX3tSsk6raRMWstJNqMBb4vQABs54Zd8IohboSAGZW3M87CRiVmQEDKwvrC8y4aaNmfV33q03EppQnaJArZDx\"\n }\n}",
+ "form": []
+ },
+ "tests": []
+ },
+ {
+ "_id": "963b9526-893e-4ff4-9543-6d841afc6a15",
+ "colId": "aa8793c8-dbc4-44d0-844a-fe6a53e53f61",
+ "containerId": "",
+ "name": "cards_check",
+ "url": "https://checkout.test.paycom.uz/api/",
+ "method": "POST",
+ "sortNum": 90000,
+ "created": "2023-08-04T06:35:53.685Z",
+ "modified": "2023-08-04T06:37:50.007Z",
+ "headers": [
+ {
+ "name": "X-Auth",
+ "value": "$payme_id"
+ },
+ {
+ "name": "Accept",
+ "value": "*/*",
+ "isDisabled": true
+ },
+ {
+ "name": "User-Agent",
+ "value": "Thunder Client (https://www.thunderclient.com)",
+ "isDisabled": true
+ }
+ ],
+ "params": [],
+ "body": {
+ "type": "json",
+ "raw": "{\n \"id\": 123,\n \"method\": \"cards.check\",\n \"params\": {\n \"token\": \"6321688682dcb3b90def1ff5_JMry9v8Ko0SAT8D5HGHZfCxi5RFHIudX9adt6ZqWD3uQgy9VTYGovP9ceIoXOq4KjPe9pyCm33cfGAUJ2WZgrThXRqnNzYrzvKo34fyH3UrEde9kaeqtk79sz4ZN3RNXHn6PwknEqONVi9yhS0Uv16OgY7wsiIfCZufayiwfYAKevCngcprYsZrJNpnheUjS56hnFyaRMR4KaPnEXCJXZkdxuiICk2m8BipM5hYhmfopQImik4j5GOZucTmUj3Ez3vGzwrwM3Z4sEBpmBJpaiaIahbncCosCEG11RDqHWj9jWOJrR3ipc7i0xCHM2zRIq1ICG9nO78rZvQ9v1FRQAuef0fUODQUmcOYcGAuKsdfKFrBwo5rxEHKTVpzuZDGN2zMS5J\"\n }\n}",
+ "form": []
+ },
+ "tests": []
+ },
+ {
+ "_id": "86e70250-4947-4770-9a90-b4ed583c7f50",
+ "colId": "aa8793c8-dbc4-44d0-844a-fe6a53e53f61",
+ "containerId": "",
+ "name": "receipts_create",
+ "url": "https://checkout.test.paycom.uz/api/",
+ "method": "POST",
+ "sortNum": 100000,
+ "created": "2023-08-04T06:35:53.686Z",
+ "modified": "2023-08-04T06:37:59.590Z",
+ "headers": [
+ {
+ "name": "X-Auth",
+ "value": "$payme_id"
+ },
+ {
+ "name": "Accept",
+ "value": "*/*",
+ "isDisabled": true
+ },
+ {
+ "name": "User-Agent",
+ "value": "Thunder Client (https://www.thunderclient.com)",
+ "isDisabled": true
+ }
+ ],
+ "params": [],
+ "body": {
+ "type": "json",
+ "raw": "{\n \"id\": \"paytechuz\",\n \"method\": \"receipts.create\",\n \"params\": {\n \"amount\": 400000,\n \"account\": {\n \"order_id\": 106\n }\n }\n}",
+ "form": []
+ },
+ "tests": []
+ },
+ {
+ "_id": "a4eed948-ab23-4b9f-8693-4d59a35e0ac2",
+ "colId": "aa8793c8-dbc4-44d0-844a-fe6a53e53f61",
+ "containerId": "",
+ "name": "receipts_pay",
+ "url": "https://checkout.test.paycom.uz/api/",
+ "method": "POST",
+ "sortNum": 120000,
+ "created": "2023-08-04T06:35:53.688Z",
+ "modified": "2023-08-04T06:38:33.561Z",
+ "headers": [
+ {
+ "name": "X-Auth",
+ "value": "$payme_id:$payme_key"
+ },
+ {
+ "name": "Accept",
+ "value": "*/*",
+ "isDisabled": true
+ },
+ {
+ "name": "User-Agent",
+ "value": "Thunder Client (https://www.thunderclient.com)",
+ "isDisabled": true
+ }
+ ],
+ "params": [],
+ "body": {
+ "type": "json",
+ "raw": "{\n \"id\": \"paytechuz\",\n \"method\": \"receipts.pay\",\n \"params\": {\n \"id\": \"63119becc4420cbf2712a24c\",\n \"token\": \"64232286890565aa4e37c2b0_TnOzC2HkPKJu6ndDeHKdyR4cQU6aIvauqqVqKmmmMFMrNTH0sByAQuPpOUTaPswth0Bxj9VKYDUNsgBhRIgIQydvH8C1iyca0wJING9kNvFemDEWUUutbBW5e1Fjh8VxYNak7Qm6Yac1tty6qgDxHnTfFMzfw5Svrq3fM8RjCr5F7IDgySRi02CJiXyNwCZxnhZtgmmimhApsXDySxyFjW1hDERh2hvZYEZMWyohnX6yaadKpOFv0QiOSWYyrMXPa1HfMmpFFaiCzjX6eOBFJJZhuJJsGxqxxgQBeuRBUOtnSAnrmzxj8j1sOEAMnIISjpZo3wABui2h7KpwIEWg9cmsuRHzYiw3NZFPKmWu5Q7WAYXDcuCBx7X5XwtJFIdUo559iN\",\n \"payer\": {\n \"phone\": \"998901304527\"\n }\n }\n}",
+ "form": []
+ },
+ "tests": []
+ },
+ {
+ "_id": "6762ba18-7042-4f51-b6de-4db048d21ef6",
+ "colId": "aa8793c8-dbc4-44d0-844a-fe6a53e53f61",
+ "containerId": "",
+ "name": "receipts_send",
+ "url": "https://checkout.test.paycom.uz/api/",
+ "method": "POST",
+ "sortNum": 130000,
+ "created": "2023-08-04T06:35:53.689Z",
+ "modified": "2023-08-04T06:38:45.337Z",
+ "headers": [
+ {
+ "name": "X-Auth",
+ "value": "$payme_id:$payme_key"
+ },
+ {
+ "name": "Accept",
+ "value": "*/*",
+ "isDisabled": true
+ },
+ {
+ "name": "User-Agent",
+ "value": "Thunder Client (https://www.thunderclient.com)",
+ "isDisabled": true
+ }
+ ],
+ "params": [],
+ "body": {
+ "type": "json",
+ "raw": "{\n \"id\": \"paytechuz\",\n \"method\": \"receipts.send\",\n \"params\": {\n \"id\": \"63119becc4420cbf2712a24c\",\n \"phone\": \"998901304527\"\n }\n}",
+ "form": []
+ },
+ "tests": []
+ },
+ {
+ "_id": "eb2be749-6f9f-4e9e-a15c-9da61e0b56fc",
+ "colId": "aa8793c8-dbc4-44d0-844a-fe6a53e53f61",
+ "containerId": "",
+ "name": "receipts_cancel",
+ "url": "https://checkout.test.paycom.uz/api/",
+ "method": "POST",
+ "sortNum": 140000,
+ "created": "2023-08-04T06:35:53.690Z",
+ "modified": "2023-08-04T06:38:55.408Z",
+ "headers": [
+ {
+ "name": "X-Auth",
+ "value": "$payme_id:$payme_key"
+ },
+ {
+ "name": "Accept",
+ "value": "*/*",
+ "isDisabled": true
+ },
+ {
+ "name": "User-Agent",
+ "value": "Thunder Client (https://www.thunderclient.com)",
+ "isDisabled": true
+ }
+ ],
+ "params": [],
+ "body": {
+ "type": "json",
+ "raw": "{\n \"id\": \"paytechuz\",\n \"method\": \"receipts.cancel\",\n \"params\": {\n \"id\": \"63119becc4420cbf2712a24c\"\n }\n}",
+ "form": []
+ },
+ "tests": []
+ },
+ {
+ "_id": "5b920c33-0fff-4c3c-ad64-5b45c3437bbf",
+ "colId": "aa8793c8-dbc4-44d0-844a-fe6a53e53f61",
+ "containerId": "",
+ "name": "receipts_check",
+ "url": "https://checkout.test.paycom.uz/api/",
+ "method": "POST",
+ "sortNum": 150000,
+ "created": "2023-08-04T06:35:53.691Z",
+ "modified": "2023-08-04T06:39:09.282Z",
+ "headers": [
+ {
+ "name": "X-Auth",
+ "value": "$payme_id:$payme_key"
+ },
+ {
+ "name": "Accept",
+ "value": "*/*",
+ "isDisabled": true
+ },
+ {
+ "name": "User-Agent",
+ "value": "Thunder Client (https://www.thunderclient.com)",
+ "isDisabled": true
+ }
+ ],
+ "params": [],
+ "body": {
+ "type": "json",
+ "raw": "{\n \"id\": \"paytechuz\",\n \"method\": \"receipts.check\",\n \"params\": {\n \"id\": \"635aa3295f103c97ef1c7606\"\n }\n}",
+ "form": []
+ },
+ "tests": []
+ },
+ {
+ "_id": "37802143-30de-493f-a439-3b2e35c397c7",
+ "colId": "aa8793c8-dbc4-44d0-844a-fe6a53e53f61",
+ "containerId": "",
+ "name": "reciepts_get",
+ "url": "https://checkout.test.paycom.uz/api/",
+ "method": "POST",
+ "sortNum": 160000,
+ "created": "2023-08-04T06:35:53.692Z",
+ "modified": "2023-08-04T06:39:20.085Z",
+ "headers": [
+ {
+ "name": "X-Auth",
+ "value": "$payme_id:$payme_key"
+ },
+ {
+ "name": "Accept",
+ "value": "*/*",
+ "isDisabled": true
+ },
+ {
+ "name": "User-Agent",
+ "value": "Thunder Client (https://www.thunderclient.com)",
+ "isDisabled": true
+ }
+ ],
+ "params": [],
+ "body": {
+ "type": "json",
+ "raw": "{\n \"id\": \"paytechuz\",\n \"method\": \"receipts.get\",\n \"params\": {\n \"id\": \"6311946bc4420cbf2712a247\"\n }\n}",
+ "form": []
+ },
+ "tests": []
+ },
+ {
+ "_id": "8fde8e80-d6e7-4020-961a-e4e0b6fbabd9",
+ "colId": "aa8793c8-dbc4-44d0-844a-fe6a53e53f61",
+ "containerId": "",
+ "name": "reciepts_get_all",
+ "url": "https://checkout.test.paycom.uz/api/",
+ "method": "POST",
+ "sortNum": 170000,
+ "created": "2023-08-04T06:35:53.693Z",
+ "modified": "2023-08-04T06:39:31.013Z",
+ "headers": [
+ {
+ "name": "X-Auth",
+ "value": "$payme_id:$payme_key"
+ },
+ {
+ "name": "Accept",
+ "value": "*/*",
+ "isDisabled": true
+ },
+ {
+ "name": "User-Agent",
+ "value": "Thunder Client (https://www.thunderclient.com)",
+ "isDisabled": true
+ }
+ ],
+ "params": [],
+ "body": {
+ "type": "json",
+ "raw": "{\n \"id\": \"paytechuz\",\n \"method\": \"receipts.get_all\",\n \"params\": {\n \"count\": 2,\n \"from\": 1612640000,\n \"to\": 1612726400,\n \"offset\": 0\n }\n}",
+ "form": []
+ },
+ "tests": []
+ },
+ {
+ "_id": "228215da-5087-4c3d-b694-8e3f02516a38",
+ "colId": "aa8793c8-dbc4-44d0-844a-fe6a53e53f61",
+ "containerId": "",
+ "name": "get_fiskal_data",
+ "url": "https://checkout.test.paycom.uz/api/",
+ "method": "POST",
+ "sortNum": 190000,
+ "created": "2023-08-04T06:35:53.694Z",
+ "modified": "2023-08-04T06:39:38.314Z",
+ "headers": [
+ {
+ "name": "X-Auth",
+ "value": "$payme_id:$payme_key"
+ },
+ {
+ "name": "Accept",
+ "value": "*/*",
+ "isDisabled": true
+ },
+ {
+ "name": "User-Agent",
+ "value": "Thunder Client (https://www.thunderclient.com)",
+ "isDisabled": true
+ }
+ ],
+ "params": [],
+ "body": {
+ "type": "json",
+ "raw": "{\n \"id\": \"paytechuz\",\n \"method\": \"receipts.set_fiscal_data\",\n \"params\": {\n \"id\": 1,\n \"fiscal_data\": {\n \"status_code\": 1,\n \"message\": 1,\n \"terminal_id\": 1,\n \"receipt_id\": 1,\n \"date\": 1,\n \"fiscal_sign\": 1,\n \"qr_code_url\": 1\n }\n }\n}",
+ "form": []
+ },
+ "tests": []
+ },
+ {
+ "_id": "c8d1791b-75a5-4287-aab2-abe656eba1f1",
+ "colId": "aa8793c8-dbc4-44d0-844a-fe6a53e53f61",
+ "containerId": "41aa7417-7725-4863-9baa-b3fa3e069fc6",
+ "name": "check-perform-transaction",
+ "url": "http://localhost:8000/payments/merchant/",
+ "method": "POST",
+ "sortNum": 210000,
+ "created": "2023-08-04T06:35:53.695Z",
+ "modified": "2023-08-04T06:41:24.064Z",
+ "headers": [
+ {
+ "name": "AUTHORIZATION",
+ "value": "Basic XXX"
+ },
+ {
+ "name": "Accept",
+ "value": "*/*",
+ "isDisabled": true
+ },
+ {
+ "name": "User-Agent",
+ "value": "Thunder Client (https://www.thunderclient.com)",
+ "isDisabled": true
+ }
+ ],
+ "params": [],
+ "body": {
+ "type": "json",
+ "raw": "{\n \"jsonrpc\": \"2.0\",\n \"method\": \"CheckPerformTransaction\",\n \"params\": {\n \"amount\": 100,\n \"account\": {\n \"order_id\": \"3\"\n }\n }\n}",
+ "form": []
+ },
+ "tests": []
+ },
+ {
+ "_id": "909d337d-dad1-4673-bc83-48fc31c0dac5",
+ "colId": "aa8793c8-dbc4-44d0-844a-fe6a53e53f61",
+ "containerId": "41aa7417-7725-4863-9baa-b3fa3e069fc6",
+ "name": "cancel-transaction",
+ "url": "http://localhost:8000/payments/merchant/",
+ "method": "POST",
+ "sortNum": 220000,
+ "created": "2023-08-04T06:35:53.696Z",
+ "modified": "2023-08-04T06:41:36.355Z",
+ "headers": [
+ {
+ "name": "AUTHORIZATION",
+ "value": "Basic XXX"
+ },
+ {
+ "name": "Accept",
+ "value": "*/*",
+ "isDisabled": true
+ },
+ {
+ "name": "User-Agent",
+ "value": "Thunder Client (https://www.thunderclient.com)",
+ "isDisabled": true
+ }
+ ],
+ "params": [],
+ "body": {
+ "type": "json",
+ "raw": "{\n \"jsonrpc\": \"2.0\",\n \"method\": \"CheckPerformTransaction\",\n \"params\": {\n \"amount\": 100,\n \"account\": {\n \"order_id\": \"3\"\n }\n }\n}",
+ "form": []
+ },
+ "tests": []
+ },
+ {
+ "_id": "eafb09b0-43b8-4e28-aa44-5cc39c631a8b",
+ "colId": "aa8793c8-dbc4-44d0-844a-fe6a53e53f61",
+ "containerId": "41aa7417-7725-4863-9baa-b3fa3e069fc6",
+ "name": "get-statement",
+ "url": "http://localhost:8000/payments/merchant/",
+ "method": "POST",
+ "sortNum": 230000,
+ "created": "2023-08-04T06:35:53.697Z",
+ "modified": "2023-08-04T06:41:52.831Z",
+ "headers": [
+ {
+ "name": "AUTHORIZATION",
+ "value": "Basic XXX"
+ },
+ {
+ "name": "Accept",
+ "value": "*/*",
+ "isDisabled": true
+ },
+ {
+ "name": "User-Agent",
+ "value": "Thunder Client (https://www.thunderclient.com)",
+ "isDisabled": true
+ }
+ ],
+ "params": [],
+ "body": {
+ "type": "json",
+ "raw": "{\n \"method\" : \"GetStatement\",\n \"params\" : {\n \"from\" : 1666462755066,\n \"to\" : 1690672447727\n }\n}",
+ "form": []
+ },
+ "tests": []
+ }
+ ],
+ "settings": {
+ "headers": [
+ {
+ "name": "Authorization",
+ "value": "Basic UGF5Y29tOnlISTNSQTFSTiZINWYwU3ZjcnhAdnE5bXVOc21IVW80OWRUdg=="
+ }
+ ],
+ "tests": []
+ }
+}
\ No newline at end of file
diff --git a/lib/payme/__init__.py b/lib/payme/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/lib/payme/admin.py b/lib/payme/admin.py
new file mode 100644
index 0000000..c5cf4b1
--- /dev/null
+++ b/lib/payme/admin.py
@@ -0,0 +1,11 @@
+from django.contrib import admin
+
+from payme.models import CUSTOM_ORDER
+from payme.models import Order as DefaultOrderModel
+
+from payme.models import MerchatTransactionsModel
+
+if not CUSTOM_ORDER:
+ admin.site.register(DefaultOrderModel)
+
+admin.site.register(MerchatTransactionsModel)
diff --git a/lib/payme/apps.py b/lib/payme/apps.py
new file mode 100644
index 0000000..52fd71f
--- /dev/null
+++ b/lib/payme/apps.py
@@ -0,0 +1,10 @@
+from django.apps import AppConfig
+
+
+class PaymeConfig(AppConfig):
+ """
+ PaymeConfig AppConfig \
+ That is used to configure the payme application with django settings.
+ """
+ default_auto_field = 'django.db.models.BigAutoField'
+ name = 'payme'
diff --git a/lib/payme/cards/__init__.py b/lib/payme/cards/__init__.py
new file mode 100644
index 0000000..c11d497
--- /dev/null
+++ b/lib/payme/cards/__init__.py
@@ -0,0 +1 @@
+from .import subscribe_cards
diff --git a/lib/payme/cards/subscribe_cards.py b/lib/payme/cards/subscribe_cards.py
new file mode 100644
index 0000000..e748ffa
--- /dev/null
+++ b/lib/payme/cards/subscribe_cards.py
@@ -0,0 +1,166 @@
+from payme.utils.to_json import to_json
+from payme.decorators.decorators import payme_request
+
+
+class PaymeSubscribeCards:
+ """
+ The PaymeSubscribeCards class inclues
+ all paycom methods which are belongs to cards.
+
+ Parameters
+ ----------
+ base_url: str — The base url of the paycom api
+ paycom_id: str — The paycom_id uses to identify
+ timeout: int — How many seconds to wait for the server to send data
+
+ Full method documentation
+ -------------------------
+ https://developer.help.paycom.uz/metody-subscribe-api/
+ """
+ def __init__(
+ self,
+ base_url: str,
+ paycom_id: str,
+ timeout=5
+ ) -> "PaymeSubscribeCards":
+ self.base_url: str = base_url
+ self.timeout: int = timeout
+ self.headers: dict = {
+ "X-Auth": paycom_id,
+ }
+ self.__methods: dict = {
+ "cards_check": "cards.check",
+ "cards_create": "cards.create",
+ "cards_remove": "cards.remove",
+ "cards_verify": "cards.verify",
+ "cards_get_verify_code": "cards.get_verify_code",
+ }
+
+ @payme_request
+ def __request(self, data) -> dict:
+ """
+ Use this private method to request.
+ On success,response will be OK with format JSON.
+
+ Parameters
+ ----------
+ data: dict — Includes request data.
+
+ Returns dictionary Payme Response
+ ---------------------------------
+ """
+ return data
+
+ def cards_create(self, number: str, expire: str, save: bool = True) -> dict:
+ """
+ Use this method to create a new card's token.
+
+ Parameters
+ ----------
+ number: str — The card number maximum length 18 char
+ expire: str — The card expiration string maximum length 5 char
+ save: bool \
+ Type of token. Optional parameter
+ The option is enabled or disabled depending on the application's business logic
+ If the flag is true, the token can be used for further payments
+ if the flag is false the token can only be used once
+ The one-time token is deleted after payment
+
+ Full method documentation
+ -------------------------
+ https://developer.help.paycom.uz/metody-subscribe-api/cards.create
+ """
+ data: dict = {
+ "method": self.__methods.get("cards_create"),
+ "params": {
+ "card": {
+ "number": number,
+ "expire": expire,
+ },
+ "save": save,
+ }
+ }
+ return self.__request(to_json(**data))
+
+ def card_get_verify_code(self, token: str) -> dict:
+ """
+ Use this method to get the verification code.
+
+ Parameters
+ ----------
+ token: str — The card's non-active token
+
+ Full method documentation
+ -------------------------
+ https://developer.help.paycom.uz/metody-subscribe-api/cards.get_verify_code
+ """
+ data: dict = {
+ "method": self.__methods.get('cards_get_verify_code'),
+ "params": {
+ "token": token,
+ }
+ }
+ return self.__request(to_json(**data))
+
+ def cards_verify(self, verify_code: int, token: str) -> dict:
+ """
+ Verification of the card using the code sent via SMS.
+
+ Parameters
+ ----------
+ verify_code: int — Code for verification
+ token: str — The card's non-active token
+
+ Full method documentation
+ -------------------------
+ https://developer.help.paycom.uz/metody-subscribe-api/cards.verify
+ """
+ data: dict = {
+ "method": self.__methods.get("cards_verify"),
+ "params": {
+ "token": token,
+ "code": verify_code
+ }
+ }
+ return self.__request(to_json(**data))
+
+ def cards_check(self, token: str) -> dict:
+ """
+ Checking the card token active or non-active.
+
+ Parameters
+ ----------
+ token: str — The card's non-active token
+
+ Full method documentation
+ -------------------------
+ https://developer.help.paycom.uz/metody-subscribe-api/cards.check
+ """
+ data: dict = {
+ "method": self.__methods.get("cards_check"),
+ "params": {
+ "token": token,
+ }
+ }
+
+ return self.__request(to_json(**data))
+
+ def cards_remove(self, token: str) -> dict:
+ """
+ Delete card's token on success returns success.
+
+ Parameters
+ ----------
+ token: str — The card's non-active token
+
+ Full method documentation
+ -------------------------
+ https://developer.help.paycom.uz/metody-subscribe-api/cards.remove
+ """
+ data: dict = {
+ "method": self.__methods.get("cards_remove"),
+ "params": {
+ "token": token,
+ }
+ }
+ return self.__request(to_json(**data))
diff --git a/lib/payme/decorators/__init__.py b/lib/payme/decorators/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/lib/payme/decorators/decorators.py b/lib/payme/decorators/decorators.py
new file mode 100644
index 0000000..b035333
--- /dev/null
+++ b/lib/payme/decorators/decorators.py
@@ -0,0 +1,34 @@
+import functools
+
+from requests import request
+from requests.exceptions import Timeout
+from requests.exceptions import RequestException
+
+from payme.utils.logging import logger
+
+from ..errors.exceptions import PaymeTimeoutException
+
+
+def payme_request(func):
+ """
+ Payme request decorator.
+ """
+ @functools.wraps(func)
+ def wrapper(self, data):
+ response = None
+ req_data = {
+ "method": "POST",
+ "url": self.base_url,
+ "data": data,
+ "headers": self.headers,
+ "timeout": self.timeout,
+ }
+ try:
+ response = request(**req_data)
+ response.raise_for_status()
+ except (Timeout, RequestException) as error:
+ logger.info("Payme request has been failed as error: %s", error)
+ raise PaymeTimeoutException() from error
+ return response.json()
+
+ return wrapper
diff --git a/lib/payme/errors/__init__.py b/lib/payme/errors/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/lib/payme/errors/exceptions.py b/lib/payme/errors/exceptions.py
new file mode 100644
index 0000000..feb2e78
--- /dev/null
+++ b/lib/payme/errors/exceptions.py
@@ -0,0 +1,89 @@
+from rest_framework.exceptions import APIException
+
+
+class BasePaymeException(APIException):
+ """
+ BasePaymeException it's APIException.
+ """
+ status_code = 200
+ error_code = None
+ message = None
+
+ # pylint: disable=super-init-not-called
+ def __init__(self, error_message: str = None):
+ detail: dict = {
+ "error": {
+ "code": self.error_code,
+ "message": self.message,
+ "data": error_message
+ }
+ }
+ self.detail = detail
+
+
+class PermissionDenied(BasePaymeException):
+ """
+ PermissionDenied APIException \
+ That is raised when the client is not allowed to server.
+ """
+ status_code = 200
+ error_code = -32504
+ message = "Permission denied"
+
+
+class MethodNotFound(BasePaymeException):
+ """
+ MethodNotFound APIException \
+ That is raised when the method does not exist.
+ """
+ status_code = 405
+ error_code = -32601
+ message = 'Method not found'
+
+
+class TooManyRequests(BasePaymeException):
+ """
+ TooManyRequests APIException \
+ That is raised when the request exceeds the limit.
+ """
+ status_code = 200
+ error_code = -31099
+ message = {
+ "uz": "Buyurtma tolovni amalga oshirish jarayonida",
+ "ru": "Транзакция в очереди",
+ "en": "Order payment status is queued"
+ }
+
+
+class IncorrectAmount(BasePaymeException):
+ """
+ IncorrectAmount APIException \
+ That is raised when the amount is not incorrect.
+ """
+ status_code = 200
+ error_code = -31001
+ message = {
+ 'ru': 'Неверная сумма',
+ 'uz': 'Incorrect amount',
+ 'en': 'Incorrect amount',
+ }
+
+
+class PerformTransactionDoesNotExist(BasePaymeException):
+ """
+ PerformTransactionDoesNotExist APIException \
+ That is raised when a transaction does not exist or deleted.
+ """
+ status_code = 200
+ error_code = -31050
+ message = {
+ "uz": "Buyurtma topilmadi",
+ "ru": "Заказ не существует",
+ "en": "Order does not exists"
+ }
+
+
+class PaymeTimeoutException(Exception):
+ """
+ Payme timeout exception that means that payme is working slowly.
+ """
diff --git a/lib/payme/methods/__init__.py b/lib/payme/methods/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/lib/payme/methods/cancel_transaction.py b/lib/payme/methods/cancel_transaction.py
new file mode 100644
index 0000000..d318480
--- /dev/null
+++ b/lib/payme/methods/cancel_transaction.py
@@ -0,0 +1,54 @@
+import time
+
+from django.db import transaction
+
+from payme.utils.logging import logger
+from payme.models import MerchatTransactionsModel
+from payme.errors.exceptions import PerformTransactionDoesNotExist
+from payme.serializers import MerchatTransactionsModelSerializer as MTMS
+
+
+class CancelTransaction:
+ """
+ CancelTransaction class
+ That is used to cancel a transaction.
+
+ Full method documentation
+ -------------------------
+ https://developer.help.paycom.uz/metody-merchant-api/canceltransaction
+ """
+
+ @transaction.atomic
+ def __call__(self, params: dict):
+ clean_data: dict = MTMS.get_validated_data(
+ params=params
+ )
+ try:
+ with transaction.atomic():
+ transactions: MerchatTransactionsModel = \
+ MerchatTransactionsModel.objects.filter(
+ _id=clean_data.get('_id'),
+ ).first()
+ if transactions.cancel_time == 0:
+ transactions.cancel_time = int(time.time() * 1000)
+ if transactions.perform_time == 0:
+ transactions.state = -1
+ if transactions.perform_time != 0:
+ transactions.state = -2
+ transactions.reason = clean_data.get("reason")
+ transactions.save()
+
+ except PerformTransactionDoesNotExist as error:
+ logger.error("Paycom transaction does not exist: %s", error)
+ raise PerformTransactionDoesNotExist() from error
+
+ response: dict = {
+ "result": {
+ "state": transactions.state,
+ "cancel_time": transactions.cancel_time,
+ "transaction": transactions.transaction_id,
+ "reason": int(transactions.reason),
+ }
+ }
+
+ return transactions.order_id, response
diff --git a/lib/payme/methods/check_perform_transaction.py b/lib/payme/methods/check_perform_transaction.py
new file mode 100644
index 0000000..78a7411
--- /dev/null
+++ b/lib/payme/methods/check_perform_transaction.py
@@ -0,0 +1,26 @@
+from payme.utils.get_params import get_params
+from payme.serializers import MerchatTransactionsModelSerializer
+
+
+class CheckPerformTransaction:
+ """
+ CheckPerformTransaction class
+ That's used to check perform transaction.
+
+ Full method documentation
+ -------------------------
+ https://developer.help.paycom.uz/metody-merchant-api/checktransaction
+ """
+ def __call__(self, params: dict) -> dict:
+ serializer = MerchatTransactionsModelSerializer(
+ data=get_params(params)
+ )
+ serializer.is_valid(raise_exception=True)
+
+ response = {
+ "result": {
+ "allow": True,
+ }
+ }
+
+ return None, response
diff --git a/lib/payme/methods/check_transaction.py b/lib/payme/methods/check_transaction.py
new file mode 100644
index 0000000..4768154
--- /dev/null
+++ b/lib/payme/methods/check_transaction.py
@@ -0,0 +1,43 @@
+from django.db import DatabaseError
+
+from payme.utils.logging import logger
+from payme.models import MerchatTransactionsModel
+from payme.serializers import MerchatTransactionsModelSerializer as MTMS
+
+
+class CheckTransaction:
+ """
+ CheckTransaction class
+ That's used to check transaction
+
+ Full method documentation
+ -------------------------
+ https://developer.help.paycom.uz/metody-merchant-api/checkperformtransaction
+ """
+ def __call__(self, params: dict) -> None:
+ clean_data: dict = MTMS.get_validated_data(
+ params=params
+ )
+
+ try:
+ transaction = \
+ MerchatTransactionsModel.objects.get(
+ _id=clean_data.get("_id"),
+ )
+ response = {
+ "result": {
+ "create_time": int(transaction.created_at_ms),
+ "perform_time": transaction.perform_time,
+ "cancel_time": transaction.cancel_time,
+ "transaction": transaction.transaction_id,
+ "state": transaction.state,
+ "reason": None,
+ }
+ }
+ if transaction.reason is not None:
+ response["result"]["reason"] = int(transaction.reason)
+
+ except DatabaseError as error:
+ logger.error("Error getting transaction in database: %s", error)
+
+ return None, response
diff --git a/lib/payme/methods/create_transaction.py b/lib/payme/methods/create_transaction.py
new file mode 100644
index 0000000..a5f2c77
--- /dev/null
+++ b/lib/payme/methods/create_transaction.py
@@ -0,0 +1,68 @@
+import uuid
+import time
+import datetime
+
+from payme.utils.logging import logger
+from payme.utils.get_params import get_params
+from payme.models import MerchatTransactionsModel
+from payme.errors.exceptions import TooManyRequests
+from payme.serializers import MerchatTransactionsModelSerializer
+
+
+class CreateTransaction:
+ """
+ CreateTransaction class
+ That's used to create transaction
+
+ Full method documentation
+ -------------------------
+ https://developer.help.paycom.uz/metody-merchant-api/createtransaction
+ """
+ def __call__(self, params: dict) -> dict:
+ serializer = MerchatTransactionsModelSerializer(
+ data=get_params(params)
+ )
+ serializer.is_valid(raise_exception=True)
+ order_id = serializer.validated_data.get("order_id")
+
+ try:
+ transaction = MerchatTransactionsModel.objects.filter(
+ order_id=order_id
+ ).last()
+
+ if transaction is not None:
+ if transaction._id != serializer.validated_data.get("_id"):
+ raise TooManyRequests()
+
+ except TooManyRequests as error:
+ logger.error("Too many requests for transaction %s", error)
+ raise TooManyRequests() from error
+
+ if transaction is None:
+ transaction, _ = \
+ MerchatTransactionsModel.objects.get_or_create(
+ _id=serializer.validated_data.get('_id'),
+ order_id=serializer.validated_data.get('order_id'),
+ transaction_id=uuid.uuid4(),
+ amount=serializer.validated_data.get('amount'),
+ created_at_ms=int(time.time() * 1000),
+ )
+
+ if transaction:
+ response: dict = {
+ "result": {
+ "create_time": int(transaction.created_at_ms),
+ "transaction": transaction.transaction_id,
+ "state": int(transaction.state),
+ }
+ }
+
+ return order_id, response
+
+ @staticmethod
+ def _convert_ms_to_datetime(time_ms: str) -> int:
+ """Use this format to convert from time ms to datetime format.
+ """
+ readable_datetime = datetime.datetime.fromtimestamp(time_ms / 1000)
+
+ return readable_datetime
diff --git a/lib/payme/methods/generate_link.py b/lib/payme/methods/generate_link.py
new file mode 100644
index 0000000..0738315
--- /dev/null
+++ b/lib/payme/methods/generate_link.py
@@ -0,0 +1,74 @@
+import base64
+from decimal import Decimal
+from dataclasses import dataclass
+
+from django.conf import settings
+
+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')
+PAYME_URL = settings.PAYME.get("PAYME_URL")
+
+
+@dataclass
+class GeneratePayLink:
+ """
+ GeneratePayLink dataclass
+ That's used to generate pay lint for each order.
+
+ Parameters
+ ----------
+ order_id: int — The order_id for paying
+ amount: int — The amount belong to the order
+
+ Returns str — pay link
+ ----------------------
+
+ Full method documentation
+ -------------------------
+ https://developer.help.paycom.uz/initsializatsiya-platezhey/
+ """
+ order_id: str
+ amount: Decimal
+
+ def generate_link(self) -> str:
+ """
+ GeneratePayLink for each order.
+ """
+ generated_pay_link: str = "{payme_url}/{encode_params}"
+ params: str = 'm={payme_id};ac.{payme_account}={order_id};a={amount};c={call_back_url}'
+
+ params = params.format(
+ payme_id=PAYME_ID,
+ payme_account=PAYME_ACCOUNT,
+ order_id=self.order_id,
+ amount=self.amount,
+ call_back_url=PAYME_CALL_BACK_URL
+ )
+ encode_params = base64.b64encode(params.encode("utf-8"))
+ return generated_pay_link.format(
+ payme_url=PAYME_URL,
+ encode_params=str(encode_params, 'utf-8')
+ )
+
+ @staticmethod
+ def to_tiyin(amount: Decimal) -> Decimal:
+ """
+ Convert from soum to tiyin.
+
+ Parameters
+ ----------
+ amount: Decimal -> order amount
+ """
+ return amount * 100
+
+ @staticmethod
+ def to_soum(amount: Decimal) -> Decimal:
+ """
+ Convert from tiyin to soum.
+
+ Parameters
+ ----------
+ amount: Decimal -> order amount
+ """
+ return amount / 100
diff --git a/lib/payme/methods/get_statement.py b/lib/payme/methods/get_statement.py
new file mode 100644
index 0000000..ba41c7e
--- /dev/null
+++ b/lib/payme/methods/get_statement.py
@@ -0,0 +1,65 @@
+from django.db import DatabaseError
+
+from payme.utils.logging import logger
+from payme.models import MerchatTransactionsModel
+from payme.serializers import MerchatTransactionsModelSerializer as MTMS
+from payme.utils.make_aware_datetime import make_aware_datetime as mad
+
+
+class GetStatement:
+ """
+ GetStatement class
+ Transaction information is used for reconciliation
+ of merchant and Payme Business transactions.
+
+ Full method documentation
+ -------------------------
+ https://developer.help.paycom.uz/metody-merchant-api/getstatement
+ """
+
+ def __call__(self, params: dict):
+ clean_data: dict = MTMS.get_validated_data(
+ params=params
+ )
+
+ start_date, end_date = mad(
+ int(clean_data.get("start_date")),
+ int(clean_data.get("end_date"))
+ )
+
+ try:
+ transactions = \
+ MerchatTransactionsModel.objects.filter(
+ created_at__gte=start_date,
+ created_at__lte=end_date
+ )
+
+ if not transactions: # no transactions found for the period
+ return {"result": {"transactions": []}}
+
+ statements = [
+ {
+ 'id': t._id,
+ 'time': int(t.created_at.timestamp()),
+ 'amount': t.amount,
+ 'account': {'order_id': t.order_id},
+ 'create_time': t.state,
+ 'perform_time': t.perform_time,
+ 'cancel_time': t.cancel_time,
+ 'transaction': t.order_id,
+ 'state': t.state,
+ 'reason': t.reason,
+ 'receivers': [] # not implemented
+ } for t in transactions
+ ]
+
+ response: dict = {
+ "result": {
+ "transactions": statements
+ }
+ }
+ except DatabaseError as error:
+ logger.error("Error getting transaction in database: %s", error)
+ response = {"result": {"transactions": []}}
+
+ return None, response
diff --git a/lib/payme/methods/perform_transaction.py b/lib/payme/methods/perform_transaction.py
new file mode 100644
index 0000000..5312065
--- /dev/null
+++ b/lib/payme/methods/perform_transaction.py
@@ -0,0 +1,47 @@
+import time
+
+from django.db import DatabaseError
+
+from payme.utils.logging import logger
+from payme.utils.get_params import get_params
+from payme.models import MerchatTransactionsModel
+from payme.serializers import MerchatTransactionsModelSerializer
+
+
+class PerformTransaction:
+ """
+ PerformTransaction class
+ That's used to perform a transaction.
+
+ Full method documentation
+ -------------------------
+ https://developer.help.paycom.uz/metody-merchant-api/performtransaction
+ """
+ def __call__(self, params: dict) -> dict:
+ serializer = MerchatTransactionsModelSerializer(
+ data=get_params(params)
+ )
+ serializer.is_valid(raise_exception=True)
+ clean_data: dict = serializer.validated_data
+ response: dict = None
+ try:
+ transaction = \
+ MerchatTransactionsModel.objects.get(
+ _id=clean_data.get("_id"),
+ )
+ transaction.state = 2
+ if transaction.perform_time == 0:
+ transaction.perform_time = int(time.time() * 1000)
+
+ transaction.save()
+ response: dict = {
+ "result": {
+ "perform_time": int(transaction.perform_time),
+ "transaction": transaction.transaction_id,
+ "state": int(transaction.state),
+ }
+ }
+ except DatabaseError as error:
+ logger.error("error while getting transaction in db: %s", error)
+
+ return transaction.order_id, response
diff --git a/lib/payme/migrations/0001_initial.py b/lib/payme/migrations/0001_initial.py
new file mode 100644
index 0000000..eec730a
--- /dev/null
+++ b/lib/payme/migrations/0001_initial.py
@@ -0,0 +1,48 @@
+# pylint: disable=invalid-name
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+ # pylint: disable=missing-class-docstring
+ initial = True
+ dependencies = []
+
+ operations = [
+ migrations.CreateModel(
+ name='MerchatTransactionsModel',
+ 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)),
+ ],
+ ),
+ migrations.CreateModel(
+ name='Order',
+ 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)),
+ ],
+ ),
+ ]
diff --git a/lib/payme/migrations/__init__.py b/lib/payme/migrations/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/lib/payme/models.py b/lib/payme/models.py
new file mode 100644
index 0000000..52d46cf
--- /dev/null
+++ b/lib/payme/models.py
@@ -0,0 +1,61 @@
+from django.db import models
+from django.conf import settings
+from django.utils.module_loading import import_string
+from django.core.exceptions import FieldError
+
+from payme.utils.logging import logger
+
+
+class MerchatTransactionsModel(models.Model):
+ """
+ MerchatTransactionsModel class \
+ That's used for managing transactions in database.
+ """
+ _id = models.CharField(max_length=255, null=True, blank=False)
+ transaction_id = models.CharField(max_length=255, null=True, blank=False)
+ order_id = models.BigIntegerField(null=True, blank=True)
+ amount = models.FloatField(null=True, blank=True)
+ time = models.BigIntegerField(null=True, blank=True)
+ perform_time = models.BigIntegerField(null=True, default=0)
+ cancel_time = models.BigIntegerField(null=True, default=0)
+ state = models.IntegerField(null=True, default=1)
+ reason = models.CharField(max_length=255, null=True, blank=True)
+ created_at_ms = models.CharField(max_length=255, null=True, blank=True)
+ created_at = models.DateTimeField(auto_now_add=True)
+ updated_at = models.DateTimeField(auto_now=True)
+
+ def __str__(self):
+ return str(self._id)
+
+
+try:
+ CUSTOM_ORDER = import_string(settings.ORDER_MODEL)
+
+ if not isinstance(CUSTOM_ORDER, models.base.ModelBase):
+ raise TypeError("The input must be an instance of models.Model class")
+
+ # pylint: disable=protected-access
+ if 'amount' not in [f.name for f in CUSTOM_ORDER._meta.fields]:
+ raise FieldError("Missing 'amount' field in your custom order model")
+
+ Order = CUSTOM_ORDER
+except (ImportError, AttributeError):
+ logger.warning("You have no payme custom order model")
+
+ CUSTOM_ORDER = None
+
+ class Order(models.Model):
+ """
+ Order class \
+ That's used for managing order process
+ """
+ amount = models.IntegerField(null=True, blank=True)
+ created_at = models.DateTimeField(auto_now_add=True)
+ updated_at = models.DateTimeField(auto_now=True)
+
+ def __str__(self):
+ return f"ORDER ID: {self.id} - AMOUNT: {self.amount}"
+
+ class Meta:
+ # pylint: disable=missing-class-docstring
+ managed = False
diff --git a/lib/payme/receipts/__init__.py b/lib/payme/receipts/__init__.py
new file mode 100644
index 0000000..6cd8cf5
--- /dev/null
+++ b/lib/payme/receipts/__init__.py
@@ -0,0 +1 @@
+from .import subscribe_receipts
diff --git a/lib/payme/receipts/subscribe_receipts.py b/lib/payme/receipts/subscribe_receipts.py
new file mode 100644
index 0000000..a96b410
--- /dev/null
+++ b/lib/payme/receipts/subscribe_receipts.py
@@ -0,0 +1,217 @@
+from payme.utils.to_json import to_json
+from payme.decorators.decorators import payme_request
+
+
+
+class PaymeSubscribeReceipts:
+ """
+ The PaymeSubscribeReceipts class inclues
+ all paycom methods which are belongs receipts part.
+
+ Parameters
+ ----------
+ base_url string: The base url of the paycom api
+ paycom_id string: The paycom_id uses to identify
+ paycom_key string: The paycom_key uses to identify too
+
+ Full method documentation
+ -------------------------
+ https://developer.help.paycom.uz/metody-subscribe-api/
+ """
+ def __init__(
+ self,
+ base_url: str,
+ paycom_id: str,
+ paycom_key: str,
+ timeout: int = 5
+ ) -> "PaymeSubscribeReceipts":
+ self.base_url: str = base_url
+ self.headers: dict = {
+ "X-Auth": f"{paycom_id}:{paycom_key}"
+ }
+ self.__methods: dict = {
+ "receipts_get": "receipts.get",
+ "receipts_pay": "receipts.pay",
+ "receipts_send": "receipts.send",
+ "receipts_check": "receipts.check",
+ "receipts_cancel": "receipts.cancel",
+ "receipts_create": "receipts.create",
+ "receipts_get_all": "receipts.get_all",
+ }
+ self.timeout = timeout
+
+ @payme_request
+ def __request(self, data) -> dict:
+ """
+ Use this private method to request.
+ On success,response will be OK with format JSON.
+
+ Parameters
+ ----------
+ data: dict — Includes request data.
+
+ Returns dictionary Payme Response
+ ---------------------------------
+ """
+ return data
+
+ def receipts_create(self, amount: float, order_id: int) -> dict:
+ """
+ Use this method to create a new payment receipt.
+
+ Parameters
+ ----------
+ amount: float — Payment amount in tiyins
+ order_id: int — Order object ID
+
+ Full method documentation
+ -------------------------
+ https://developer.help.paycom.uz/metody-subscribe-api/receipts.create
+ """
+ data: dict = {
+ "method": self.__methods.get("receipts_create"),
+ "params": {
+ "amount": amount,
+ "account": {
+ "order_id": order_id,
+ }
+ }
+ }
+ return self.__request(to_json(**data))
+
+ def receipts_pay(self, invoice_id: str, token: str, phone: str) -> dict:
+ """
+ Use this method to pay for an exist receipt.
+
+ Parameters
+ ----------
+ invoice_id: str — Invoice id for indentity transaction
+ token: str — The card's active token
+ phone: str —The payer's phone number
+
+ Full method documentation
+ -------------------------
+ https://developer.help.paycom.uz/metody-subscribe-api/receipts.pay
+ """
+ data: dict = {
+ "method": self.__methods.get("receipts_pay"),
+ "params": {
+ "id": invoice_id,
+ "token": token,
+ "payer": {
+ "phone": phone,
+ }
+ }
+ }
+ return self.__request(to_json(**data))
+
+ def receipts_send(self, invoice_id: str, phone: str) -> dict:
+ """
+ Use this method to send a receipt for payment in an SMS message.
+
+ Parameters
+ ----------
+ invoice_id: str — The invoice id for indentity transaction
+ phone: str — The payer's phone number
+
+ Full method documentation
+ -------------------------
+ https://developer.help.paycom.uz/metody-subscribe-api/receipts.send
+ """
+ data: dict = {
+ "method": self.__methods.get('receipts_send'),
+ "params": {
+ "id": invoice_id,
+ "phone": phone
+ }
+ }
+ return self.__request(to_json(**data))
+
+ def receipts_cancel(self, invoice_id: str) -> dict:
+ """
+ Use this method a paid check in the queue for cancellation.
+
+ Parameters
+ ----------
+ invoice_id: str — The invoice id for indentity transaction
+
+ Full method documentation
+ -------------------------
+ https://developer.help.paycom.uz/metody-subscribe-api/receipts.cancel
+ """
+ data: dict = {
+ "method": self.__methods.get('receipts_cancel'),
+ "params": {
+ "id": invoice_id
+ }
+ }
+
+ return self.__request(to_json(**data))
+
+ def receipts_check(self, invoice_id: str) -> dict:
+ """
+ Use this method check for an exist receipt.
+
+ Parameters
+ ----------
+ invoice_id: str — The invoice id for indentity transaction
+
+ Full method documentation
+ -------------------------
+ https://developer.help.paycom.uz/metody-subscribe-api/receipts.check
+ """
+ data: dict = {
+ "method": self.__methods.get('receipts_check'),
+ "params": {
+ "id": invoice_id
+ }
+ }
+
+ return self.__request(to_json(**data))
+
+ def reciepts_get(self, invoice_id: str) -> dict:
+ """
+ Use this method check status for an exist receipt.
+
+ Parameters
+ ----------
+ invoice_id: str — The invoice id for indentity transaction
+
+ Full method documentation
+ -------------------------
+ https://developer.help.paycom.uz/metody-subscribe-api/receipts.get
+ """
+ data: dict = {
+ "method": self.__methods.get('receipts_get'),
+ "params": {
+ "id": invoice_id
+ }
+ }
+
+ return self.__request(to_json(**data))
+
+ def reciepts_get_all(self, count: int, _from: int, _to: int, offset: int) -> dict:
+ """
+ Use this method get all complete information, on checks for a certain period.
+
+ Parameters
+ ----------
+ count: int — The number of checks. Maximum value - 50
+ _from: str — The date of the beginning
+ _to: int — The date of the ending
+ offset: str — The number of subsequent skipped checks.
+
+ Full method documentation
+ -------------------------
+ https://developer.help.paycom.uz/metody-subscribe-api/receipts.get_all
+ """
+ data: str = {
+ "method": self.__methods.get('receipts_get_all'),
+ "params": {
+ "count": count,
+ "from": _from,
+ "to": _to,
+ "offset": offset
+ }
+ }
+ return self.__request(to_json(**data))
diff --git a/lib/payme/serializers.py b/lib/payme/serializers.py
new file mode 100644
index 0000000..8f9b3f3
--- /dev/null
+++ b/lib/payme/serializers.py
@@ -0,0 +1,88 @@
+from django.conf import settings
+
+from rest_framework import serializers
+
+from payme.models import Order
+from payme.utils.logging import logger
+from payme.utils.get_params import get_params
+from payme.models import MerchatTransactionsModel
+from payme.errors.exceptions import IncorrectAmount
+from payme.errors.exceptions import PerformTransactionDoesNotExist
+
+
+class MerchatTransactionsModelSerializer(serializers.ModelSerializer):
+ """
+ MerchatTransactionsModelSerializer class \
+ That's used to serialize merchat transactions data.
+ """
+ start_date = serializers.IntegerField(allow_null=True)
+ end_date = serializers.IntegerField(allow_null=True)
+
+ class Meta:
+ # pylint: disable=missing-class-docstring
+ model: MerchatTransactionsModel = MerchatTransactionsModel
+ fields: str = "__all__"
+ extra_fields = ['start_date', 'end_date']
+
+ def validate(self, attrs) -> dict:
+ """
+ Validate the data given to the MerchatTransactionsModel.
+ """
+ if attrs.get("order_id") is not None:
+ try:
+ order = Order.objects.get(
+ id=attrs['order_id']
+ )
+ if order.amount != int(attrs['amount']):
+ raise IncorrectAmount()
+
+ except IncorrectAmount as error:
+ logger.error("Invalid amount for order: %s", attrs['order_id'])
+ raise IncorrectAmount() from error
+
+ return attrs
+
+ def validate_amount(self, amount) -> int:
+ """
+ Validator for Transactions Amount.
+ """
+ if amount is None:
+ raise IncorrectAmount()
+
+ if int(amount) <= int(settings.PAYME.get("PAYME_MIN_AMOUNT", 0)):
+ raise IncorrectAmount("Payment amount is less than allowed.")
+
+ return amount
+
+ def validate_order_id(self, order_id) -> int:
+ """
+ Use this method to check if a transaction is allowed to be executed.
+
+ Parameters
+ ----------
+ order_id: str -> Order Indentation.
+ """
+ try:
+ Order.objects.get(id=order_id)
+ except Order.DoesNotExist as error:
+ logger.error("Order does not exist order_id: %s", order_id)
+ raise PerformTransactionDoesNotExist() from error
+
+ return order_id
+
+ @staticmethod
+ def get_validated_data(params: dict) -> dict:
+ """
+ This static method helps to get validated data.
+
+ Parameters
+ ----------
+ params: dict — Includes request params.
+ """
+ serializer = MerchatTransactionsModelSerializer(
+ data=get_params(params)
+ )
+ serializer.is_valid(raise_exception=True)
+ clean_data: dict = serializer.validated_data
+
+ return clean_data
diff --git a/lib/payme/urls.py b/lib/payme/urls.py
new file mode 100644
index 0000000..c9c7886
--- /dev/null
+++ b/lib/payme/urls.py
@@ -0,0 +1,8 @@
+from django.urls import path
+
+from payme.views import MerchantAPIView
+
+
+urlpatterns = [
+ path("merchant/", MerchantAPIView.as_view())
+]
diff --git a/lib/payme/utils/__init__.py b/lib/payme/utils/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/lib/payme/utils/get_params.py b/lib/payme/utils/get_params.py
new file mode 100644
index 0000000..8005c86
--- /dev/null
+++ b/lib/payme/utils/get_params.py
@@ -0,0 +1,24 @@
+from django.conf import settings
+
+
+def get_params(params: dict) -> dict:
+ """
+ Use this function to get the parameters from the payme.
+ """
+ account: dict = params.get("account")
+
+ clean_params: dict = {}
+ clean_params["_id"] = params.get("id")
+ clean_params["time"] = params.get("time")
+ clean_params["amount"] = params.get("amount")
+ clean_params["reason"] = params.get("reason")
+
+ # get statement method params
+ clean_params["start_date"] = params.get("from")
+ clean_params["end_date"] = params.get("to")
+
+ if account is not None:
+ account_name: str = settings.PAYME.get("PAYME_ACCOUNT")
+ clean_params["order_id"] = account[account_name]
+
+ return clean_params
diff --git a/lib/payme/utils/logging.py b/lib/payme/utils/logging.py
new file mode 100644
index 0000000..e602214
--- /dev/null
+++ b/lib/payme/utils/logging.py
@@ -0,0 +1,9 @@
+import logging
+
+logging.basicConfig(
+ level=logging.DEBUG,
+ format='%(asctime)s %(levelname)s %(message)s',
+ datefmt='%Y-%m-%d %H:%M:%S'
+)
+
+logger = logging.getLogger(__name__)
diff --git a/lib/payme/utils/make_aware_datetime.py b/lib/payme/utils/make_aware_datetime.py
new file mode 100644
index 0000000..ef2f1e7
--- /dev/null
+++ b/lib/payme/utils/make_aware_datetime.py
@@ -0,0 +1,21 @@
+from django.utils.timezone import datetime as dt
+from django.utils.timezone import make_aware
+
+
+def make_aware_datetime(start_date: int, end_date: int):
+ """
+ Convert Unix timestamps to aware datetimes.
+
+ :param start_date: Unix timestamp (milliseconds)
+ :param end_date: Unix timestamp (milliseconds)
+
+ :return: A tuple of two aware datetimes
+ """
+ return map(
+ lambda timestamp: make_aware(
+ dt.fromtimestamp(
+ timestamp / 1000
+ )
+ ),
+ [start_date, end_date]
+ )
diff --git a/lib/payme/utils/support.py b/lib/payme/utils/support.py
new file mode 100644
index 0000000..3b7f813
--- /dev/null
+++ b/lib/payme/utils/support.py
@@ -0,0 +1,8 @@
+"""
+Author: Muhammadali Akbarov
+Gmail: muhammadali17abc@gmail.com
+Phone: +998888351717
+Telegram: @Muhammadalive
+Twitter: https://twitter.com/muhammadali_abc
+GitHub: https://github.com/Muhammadali-Akbarov/
+"""
diff --git a/lib/payme/utils/to_json.py b/lib/payme/utils/to_json.py
new file mode 100644
index 0000000..cd29eba
--- /dev/null
+++ b/lib/payme/utils/to_json.py
@@ -0,0 +1,12 @@
+import json
+
+def to_json(**kwargs) -> dict:
+ """
+ Use this static method to data dumps.
+ """
+ data: dict = {
+ "method": kwargs.pop("method"),
+ "params": kwargs.pop("params"),
+ }
+
+ return json.dumps(data)
diff --git a/lib/payme/views.py b/lib/payme/views.py
new file mode 100644
index 0000000..25db03c
--- /dev/null
+++ b/lib/payme/views.py
@@ -0,0 +1,163 @@
+import base64
+import binascii
+
+from django.conf import settings
+
+from rest_framework.views import APIView
+from rest_framework.response import Response
+from rest_framework.exceptions import ValidationError
+
+from payme.utils.logging import logger
+
+from payme.errors.exceptions import MethodNotFound
+from payme.errors.exceptions import PermissionDenied
+from payme.errors.exceptions import PerformTransactionDoesNotExist
+
+from payme.methods.get_statement import GetStatement
+from payme.methods.check_transaction import CheckTransaction
+from payme.methods.cancel_transaction import CancelTransaction
+from payme.methods.create_transaction import CreateTransaction
+from payme.methods.perform_transaction import PerformTransaction
+from payme.methods.check_perform_transaction import CheckPerformTransaction
+
+
+class MerchantAPIView(APIView):
+ """
+ MerchantAPIView class provides payme call back functionality.
+ """
+ permission_classes = ()
+ authentication_classes = ()
+
+ def post(self, request) -> Response:
+ """
+ Payme sends post request to our call back url.
+ That methods are includes 5 methods
+ - CheckPerformTransaction
+ - CreateTransaction
+ - PerformTransaction
+ - CancelTransaction
+ - CheckTransaction
+ - GetStatement
+ """
+ password = request.META.get('HTTP_AUTHORIZATION')
+ if self.authorize(password):
+ incoming_data: dict = request.data
+ incoming_method: str = incoming_data.get("method")
+
+ logger.info("Call back data is incoming %s", incoming_data)
+
+ try:
+ paycom_method = self.get_paycom_method_by_name(
+ incoming_method=incoming_method
+ )
+ except ValidationError as error:
+ logger.error("Validation Error occurred: %s", error)
+ raise MethodNotFound() from error
+
+ except PerformTransactionDoesNotExist as error:
+ logger.error("PerformTransactionDoesNotExist Error occurred: %s", error)
+ raise PerformTransactionDoesNotExist() from error
+
+ order_id, action = paycom_method(incoming_data.get("params"))
+
+ if isinstance(paycom_method, CreateTransaction):
+ self.create_transaction(
+ order_id=order_id,
+ action=action,
+ )
+
+ if isinstance(paycom_method, PerformTransaction):
+ self.perform_transaction(
+ order_id=order_id,
+ action=action,
+ )
+
+ if isinstance(paycom_method, CancelTransaction):
+ self.cancel_transaction(
+ order_id=order_id,
+ action=action,
+ )
+
+ return Response(data=action)
+
+ def get_paycom_method_by_name(self, incoming_method: str) -> object:
+ """
+ Use this static method to get the paycom method by name.
+ :param incoming_method: string -> incoming method name
+ """
+ available_methods: dict = {
+ "CheckPerformTransaction": CheckPerformTransaction,
+ "CreateTransaction": CreateTransaction,
+ "PerformTransaction": PerformTransaction,
+ "CancelTransaction": CancelTransaction,
+ "CheckTransaction": CheckTransaction,
+ "GetStatement": GetStatement
+ }
+
+ try:
+ merchant_method = available_methods[incoming_method]
+ except Exception as error:
+ error_message = "Unavailable method: %s", incoming_method
+ logger.error(error_message)
+ raise MethodNotFound(error_message=error_message) from error
+
+ merchant_method = merchant_method()
+
+ return merchant_method
+
+ @staticmethod
+ def authorize(password: str) -> None:
+ """
+ Authorize the Merchant.
+ :param password: string -> Merchant authorization password
+ """
+ is_payme: bool = False
+ error_message: str = ""
+
+ if not isinstance(password, str):
+ error_message = "Request from an unauthorized source!"
+ logger.error(error_message)
+ raise PermissionDenied(error_message=error_message)
+
+ password = password.split()[-1]
+
+ try:
+ password = base64.b64decode(password).decode('utf-8')
+ except (binascii.Error, UnicodeDecodeError) as error:
+ error_message = "Error when authorize request to merchant!"
+ logger.error(error_message)
+
+ raise PermissionDenied(error_message=error_message) from error
+
+ merchant_key = password.split(':')[-1]
+
+ if merchant_key == settings.PAYME.get('PAYME_KEY'):
+ is_payme = True
+
+ if merchant_key != settings.PAYME.get('PAYME_KEY'):
+ logger.error("Invalid key in request!")
+
+ if is_payme is False:
+ raise PermissionDenied(
+ error_message="Unavailable data for unauthorized users!"
+ )
+
+ return is_payme
+
+ def create_transaction(self, order_id, action) -> None:
+ """
+ need implement in your view class
+ """
+ pass
+
+ def perform_transaction(self, order_id, action) -> None:
+ """
+ need implement in your view class
+ """
+ pass
+
+ def cancel_transaction(self,order_id, action) -> None:
+ """
+ need implement in your view class
+ """
+ pass
diff --git a/makefile b/makefile
new file mode 100644
index 0000000..3f18e6c
--- /dev/null
+++ b/makefile
@@ -0,0 +1,10 @@
+lint:
+ pylint ./lib/*
+
+upload:
+ rm -rf ./dist/*
+ python setup.py sdist
+ twine upload dist/*
+
+upload_retry:
+ twine upload dist/*
diff --git a/requirements/dev-requirements.txt b/requirements/dev-requirements.txt
new file mode 100644
index 0000000..bd8a17e
--- /dev/null
+++ b/requirements/dev-requirements.txt
@@ -0,0 +1,10 @@
+black==22.3.0
+ipdb==0.13.9
+ipython>=7.31.1
+flake8==4.0.1
+isort==5.10.1
+slotscheck==0.14.0
+twine==3.8.0
+mypy==0.961
+pip-upgrader==1.4.15
+wheel==0.38.1
diff --git a/requirements/requirements.txt b/requirements/requirements.txt
new file mode 100644
index 0000000..0739c50
--- /dev/null
+++ b/requirements/requirements.txt
@@ -0,0 +1,3 @@
+requests==2.*
+dataclasses==0.*
+djangorestframework==3.14.0
diff --git a/scripts/release.sh b/scripts/release.sh
new file mode 100755
index 0000000..d590816
--- /dev/null
+++ b/scripts/release.sh
@@ -0,0 +1,5 @@
+#!/bin/bash
+rm -rf ./build/*
+rm -rf ./dist/*
+python setup.py sdist bdist_wheel
+twine upload dist/*
diff --git a/setup.cfg b/setup.cfg
new file mode 100644
index 0000000..d07624e
--- /dev/null
+++ b/setup.cfg
@@ -0,0 +1,3 @@
+[metadata]
+description-file=README.md
+license_files=LICENSE.txt
\ No newline at end of file
diff --git a/setup.py b/setup.py
new file mode 100644
index 0000000..dce6ed4
--- /dev/null
+++ b/setup.py
@@ -0,0 +1,19 @@
+from setuptools import setup, find_packages
+
+
+setup(
+ name='payme-pkg',
+ version='2.5.3',
+ license='MIT',
+ author="Muhammadali Akbarov",
+ author_email='muhammadali17abc@gmail.com',
+ packages=find_packages('lib'),
+ package_dir={'': 'lib'},
+ url='https://github.com/Muhammadali-Akbarov/payme-pkg',
+ keywords='paymeuz paycomuz payme-merchant merchant-api subscribe-api payme-pkg payme-api',
+ install_requires=[
+ 'requests==2.*',
+ 'dataclasses==0.*',
+ 'djangorestframework==3.14.0'
+ ],
+)