From 5170382855d492389398551483b2c38180413cd3 Mon Sep 17 00:00:00 2001 From: Muhammadali-Akbarov Date: Tue, 22 Aug 2023 23:10:23 +0500 Subject: [PATCH] =?UTF-8?q?Restored=20Successfully=F0=9F=93=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/pylint.yml | 24 + .github/workflows/release.yaml | 24 + .gitignore | 10 + .pylintrc | 6 + LICENSE.txt | 20 + README.md | 893 +++++++++++++++++ .../postman/paytechuz-payme_postman.json | 928 ++++++++++++++++++ .../thunder/paytechuz-payme_thunder.json | 741 ++++++++++++++ lib/payme/__init__.py | 0 lib/payme/admin.py | 11 + lib/payme/apps.py | 10 + lib/payme/cards/__init__.py | 1 + lib/payme/cards/subscribe_cards.py | 166 ++++ lib/payme/decorators/__init__.py | 0 lib/payme/decorators/decorators.py | 34 + lib/payme/errors/__init__.py | 0 lib/payme/errors/exceptions.py | 89 ++ lib/payme/methods/__init__.py | 0 lib/payme/methods/cancel_transaction.py | 54 + .../methods/check_perform_transaction.py | 26 + lib/payme/methods/check_transaction.py | 43 + lib/payme/methods/create_transaction.py | 68 ++ lib/payme/methods/generate_link.py | 74 ++ lib/payme/methods/get_statement.py | 65 ++ lib/payme/methods/perform_transaction.py | 47 + lib/payme/migrations/0001_initial.py | 48 + lib/payme/migrations/__init__.py | 0 lib/payme/models.py | 61 ++ lib/payme/receipts/__init__.py | 1 + lib/payme/receipts/subscribe_receipts.py | 217 ++++ lib/payme/serializers.py | 88 ++ lib/payme/urls.py | 8 + lib/payme/utils/__init__.py | 0 lib/payme/utils/get_params.py | 24 + lib/payme/utils/logging.py | 9 + lib/payme/utils/make_aware_datetime.py | 21 + lib/payme/utils/support.py | 8 + lib/payme/utils/to_json.py | 12 + lib/payme/views.py | 163 +++ makefile | 10 + requirements/dev-requirements.txt | 10 + requirements/requirements.txt | 3 + scripts/release.sh | 5 + setup.cfg | 3 + setup.py | 19 + 45 files changed, 4044 insertions(+) create mode 100644 .github/workflows/pylint.yml create mode 100644 .github/workflows/release.yaml create mode 100644 .gitignore create mode 100644 .pylintrc create mode 100644 LICENSE.txt create mode 100644 README.md create mode 100644 docs/collections/postman/paytechuz-payme_postman.json create mode 100644 docs/collections/thunder/paytechuz-payme_thunder.json create mode 100644 lib/payme/__init__.py create mode 100644 lib/payme/admin.py create mode 100644 lib/payme/apps.py create mode 100644 lib/payme/cards/__init__.py create mode 100644 lib/payme/cards/subscribe_cards.py create mode 100644 lib/payme/decorators/__init__.py create mode 100644 lib/payme/decorators/decorators.py create mode 100644 lib/payme/errors/__init__.py create mode 100644 lib/payme/errors/exceptions.py create mode 100644 lib/payme/methods/__init__.py create mode 100644 lib/payme/methods/cancel_transaction.py create mode 100644 lib/payme/methods/check_perform_transaction.py create mode 100644 lib/payme/methods/check_transaction.py create mode 100644 lib/payme/methods/create_transaction.py create mode 100644 lib/payme/methods/generate_link.py create mode 100644 lib/payme/methods/get_statement.py create mode 100644 lib/payme/methods/perform_transaction.py create mode 100644 lib/payme/migrations/0001_initial.py create mode 100644 lib/payme/migrations/__init__.py create mode 100644 lib/payme/models.py create mode 100644 lib/payme/receipts/__init__.py create mode 100644 lib/payme/receipts/subscribe_receipts.py create mode 100644 lib/payme/serializers.py create mode 100644 lib/payme/urls.py create mode 100644 lib/payme/utils/__init__.py create mode 100644 lib/payme/utils/get_params.py create mode 100644 lib/payme/utils/logging.py create mode 100644 lib/payme/utils/make_aware_datetime.py create mode 100644 lib/payme/utils/support.py create mode 100644 lib/payme/utils/to_json.py create mode 100644 lib/payme/views.py create mode 100644 makefile create mode 100644 requirements/dev-requirements.txt create mode 100644 requirements/requirements.txt create mode 100755 scripts/release.sh create mode 100644 setup.cfg create mode 100644 setup.py 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' + ], +)