payme-pkg 2.6.7__tar.gz → 3.0.3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of payme-pkg might be problematic. Click here for more details.

Files changed (77) hide show
  1. {payme_pkg-2.6.7/lib/payme_pkg.egg-info → payme_pkg-3.0.3}/PKG-INFO +1 -1
  2. payme_pkg-3.0.3/README.md +125 -0
  3. payme_pkg-3.0.3/payme/__init__.py +1 -0
  4. payme_pkg-3.0.3/payme/admin.py +17 -0
  5. {payme_pkg-2.6.7/lib/my_app → payme_pkg-3.0.3/payme}/apps.py +2 -2
  6. payme_pkg-3.0.3/payme/classes/cards.py +212 -0
  7. payme_pkg-3.0.3/payme/classes/client.py +31 -0
  8. payme_pkg-3.0.3/payme/classes/http.py +106 -0
  9. payme_pkg-3.0.3/payme/classes/initializer.py +77 -0
  10. payme_pkg-3.0.3/payme/classes/receipts.py +307 -0
  11. payme_pkg-3.0.3/payme/const.py +35 -0
  12. payme_pkg-3.0.3/payme/exceptions/__init__.py +5 -0
  13. payme_pkg-3.0.3/payme/exceptions/general.py +250 -0
  14. payme_pkg-3.0.3/payme/exceptions/webhook.py +125 -0
  15. payme_pkg-3.0.3/payme/models.py +136 -0
  16. payme_pkg-3.0.3/payme/types/response/__init__.py +4 -0
  17. payme_pkg-3.0.3/payme/types/response/cards.py +110 -0
  18. payme_pkg-3.0.3/payme/types/response/receipts.py +216 -0
  19. payme_pkg-3.0.3/payme/types/response/webhook.py +136 -0
  20. payme_pkg-3.0.3/payme/urls.py +8 -0
  21. payme_pkg-3.0.3/payme/util.py +53 -0
  22. payme_pkg-3.0.3/payme/views.py +332 -0
  23. {payme_pkg-2.6.7 → payme_pkg-3.0.3/payme_pkg.egg-info}/PKG-INFO +1 -1
  24. payme_pkg-3.0.3/payme_pkg.egg-info/SOURCES.txt +33 -0
  25. payme_pkg-3.0.3/payme_pkg.egg-info/top_level.txt +1 -0
  26. {payme_pkg-2.6.7 → payme_pkg-3.0.3}/setup.py +2 -3
  27. payme_pkg-2.6.7/README.md +0 -22
  28. payme_pkg-2.6.7/lib/core/asgi.py +0 -16
  29. payme_pkg-2.6.7/lib/core/settings.py +0 -133
  30. payme_pkg-2.6.7/lib/core/urls.py +0 -25
  31. payme_pkg-2.6.7/lib/core/wsgi.py +0 -16
  32. payme_pkg-2.6.7/lib/my_app/admin.py +0 -3
  33. payme_pkg-2.6.7/lib/my_app/models.py +0 -3
  34. payme_pkg-2.6.7/lib/my_app/tests.py +0 -3
  35. payme_pkg-2.6.7/lib/my_app/views.py +0 -16
  36. payme_pkg-2.6.7/lib/payme/admin.py +0 -11
  37. payme_pkg-2.6.7/lib/payme/apps.py +0 -10
  38. payme_pkg-2.6.7/lib/payme/cards/__init__.py +0 -1
  39. payme_pkg-2.6.7/lib/payme/cards/subscribe_cards.py +0 -166
  40. payme_pkg-2.6.7/lib/payme/decorators/__init__.py +0 -0
  41. payme_pkg-2.6.7/lib/payme/decorators/decorators.py +0 -34
  42. payme_pkg-2.6.7/lib/payme/errors/__init__.py +0 -0
  43. payme_pkg-2.6.7/lib/payme/errors/exceptions.py +0 -89
  44. payme_pkg-2.6.7/lib/payme/methods/__init__.py +0 -0
  45. payme_pkg-2.6.7/lib/payme/methods/cancel_transaction.py +0 -54
  46. payme_pkg-2.6.7/lib/payme/methods/check_perform_transaction.py +0 -26
  47. payme_pkg-2.6.7/lib/payme/methods/check_transaction.py +0 -43
  48. payme_pkg-2.6.7/lib/payme/methods/create_transaction.py +0 -68
  49. payme_pkg-2.6.7/lib/payme/methods/generate_link.py +0 -83
  50. payme_pkg-2.6.7/lib/payme/methods/get_statement.py +0 -65
  51. payme_pkg-2.6.7/lib/payme/methods/perform_transaction.py +0 -47
  52. payme_pkg-2.6.7/lib/payme/migrations/0001_initial.py +0 -48
  53. payme_pkg-2.6.7/lib/payme/migrations/__init__.py +0 -0
  54. payme_pkg-2.6.7/lib/payme/models.py +0 -68
  55. payme_pkg-2.6.7/lib/payme/receipts/__init__.py +0 -1
  56. payme_pkg-2.6.7/lib/payme/receipts/subscribe_receipts.py +0 -217
  57. payme_pkg-2.6.7/lib/payme/serializers.py +0 -86
  58. payme_pkg-2.6.7/lib/payme/urls.py +0 -8
  59. payme_pkg-2.6.7/lib/payme/utils/__init__.py +0 -0
  60. payme_pkg-2.6.7/lib/payme/utils/get_params.py +0 -24
  61. payme_pkg-2.6.7/lib/payme/utils/logging.py +0 -9
  62. payme_pkg-2.6.7/lib/payme/utils/make_aware_datetime.py +0 -21
  63. payme_pkg-2.6.7/lib/payme/utils/support.py +0 -8
  64. payme_pkg-2.6.7/lib/payme/utils/to_json.py +0 -13
  65. payme_pkg-2.6.7/lib/payme/views.py +0 -163
  66. payme_pkg-2.6.7/lib/payme_pkg.egg-info/SOURCES.txt +0 -54
  67. payme_pkg-2.6.7/lib/payme_pkg.egg-info/top_level.txt +0 -3
  68. payme_pkg-2.6.7/tests/test_cards.py +0 -25
  69. payme_pkg-2.6.7/tests/test_receipts.py +0 -67
  70. {payme_pkg-2.6.7 → payme_pkg-3.0.3}/LICENSE.txt +0 -0
  71. {payme_pkg-2.6.7/lib/core → payme_pkg-3.0.3/payme/classes}/__init__.py +0 -0
  72. {payme_pkg-2.6.7/lib/my_app → payme_pkg-3.0.3/payme/migrations}/__init__.py +0 -0
  73. {payme_pkg-2.6.7/lib/my_app/migrations → payme_pkg-3.0.3/payme/types}/__init__.py +0 -0
  74. {payme_pkg-2.6.7/lib/payme → payme_pkg-3.0.3/payme/types/request}/__init__.py +0 -0
  75. {payme_pkg-2.6.7/lib → payme_pkg-3.0.3}/payme_pkg.egg-info/dependency_links.txt +0 -0
  76. {payme_pkg-2.6.7/lib → payme_pkg-3.0.3}/payme_pkg.egg-info/requires.txt +0 -0
  77. {payme_pkg-2.6.7 → payme_pkg-3.0.3}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: payme-pkg
3
- Version: 2.6.7
3
+ Version: 3.0.3
4
4
  Home-page: https://github.com/Muhammadali-Akbarov/payme-pkg
5
5
  Author: Muhammadali Akbarov
6
6
  Author-email: muhammadali17abc@gmail.com
@@ -0,0 +1,125 @@
1
+ <h1 align="center">Payme PKG</h1>
2
+
3
+
4
+ <p align="center">
5
+ <a href="https://docs.pay-tech.uz"><img src="https://img.shields.io/static/v1?message=Documented%20on%20GitBook&logo=gitbook&logoColor=ffffff&label=%20&labelColor=5c5c5c&color=3F89A1"></a>
6
+ <a href="https://github.com/PayTechUz/payme-pkg"><img src="https://img.shields.io/badge/Open_Source-❤️-FDA599?"/></a>
7
+ <a href="t.me/+DK7n7lKx8GY5ZDZi"><img src="https://img.shields.io/badge/Community-Join%20Us-blueviolet"/></a>
8
+ <a href="https://github.com/PayTechUz/payme-pkg/issues"><img src="https://img.shields.io/github/issues/gitbookIO/gitbook"/></a>
9
+ </p>
10
+
11
+ <p align="center">Welcome to payme-pkg, the open source payme sdk for python.</p>
12
+
13
+ <p align="center">You can use for test and production mode. Join our community and ask everything you need.
14
+ </p>
15
+ <a href="https://docs.pay-tech.uz">
16
+ <p align="center">Visit to full documentation for Merchant and Subcribe Api</p>
17
+ </a>
18
+ <p align="center">
19
+ <img style="width: 60%;" src="https://i.postimg.cc/WbD32bHC/payme-pkg-demo-m4a.gif">
20
+ </p>
21
+
22
+ ## Installation
23
+
24
+ ```shell
25
+ pip install payme-pkg
26
+ ```
27
+
28
+ ## Installation to Django
29
+
30
+ Add `'payme'` in to your settings.py
31
+
32
+ ```python
33
+ INSTALLED_APPS = [
34
+ ...
35
+ 'payme',
36
+ ...
37
+ ]
38
+ ```
39
+
40
+ Add `'payme'` credentials inside to settings.py
41
+
42
+ One time payment configuration settings.py
43
+ ```python
44
+ PAYME_ID = "your-payme-id"
45
+ PAYME_KEY = "your-payme-key"
46
+ PAYME_ACCOUNT_FIELD = "id"
47
+ PAYME_AMOUNT_FIELD = "total_amount"
48
+ PAYME_ACCOUNT_MODEL = "orders.models.Orders"
49
+ PAYME_ONE_TIME_PAYMENT = True
50
+ ```
51
+
52
+ Multi payment configuration settings.py
53
+ ```python
54
+ PAYME_ID = "your-payme-id"
55
+ PAYME_KEY = "your-payme-key"
56
+ PAYME_ACCOUNT_FIELD = "id"
57
+ PAYME_ACCOUNT_MODEL = "clients.models.Client"
58
+ PAYME_ONE_TIME_PAYMENT = False
59
+ ```
60
+
61
+ Create a new View that about handling call backs
62
+ ```python
63
+ from payme.views import PaymeWebHookAPIView
64
+
65
+
66
+ class PaymeCallBackAPIView(PaymeWebHookAPIView):
67
+ def handle_created_payment(self, params, result, *args, **kwargs):
68
+ """
69
+ Handle the successful payment. You can override this method
70
+ """
71
+ print(f"Transaction created for this params: {params} and cr_result: {result}")
72
+
73
+ def handle_successfully_payment(self, params, result, *args, **kwargs):
74
+ """
75
+ Handle the successful payment. You can override this method
76
+ """
77
+ print(f"Transaction successfully performed for this params: {params} and performed_result: {result}")
78
+
79
+ def handle_cancelled_payment(self, params, result, *args, **kwargs):
80
+ """
81
+ Handle the cancelled payment. You can override this method
82
+ """
83
+ print(f"Transaction cancelled for this params: {params} and cancelled_result: {result}")
84
+ ```
85
+
86
+ Add a `payme` path to core of urlpatterns:
87
+
88
+ ```python
89
+ from django.urls import path
90
+ from django.urls import include
91
+
92
+ from your_app.views import PaymeCallBackAPIView
93
+
94
+ urlpatterns = [
95
+ ...
96
+ path("payment/update/", PaymeCallBackAPIView.as_view()),
97
+ ...
98
+ ]
99
+ ```
100
+
101
+ Run migrations
102
+ ```shell
103
+ python3 manage.py makemigrations && python manage.py migrate
104
+ ```
105
+ 🎉 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.
106
+
107
+ ## Generate Pay Link
108
+
109
+ Example to generate link:
110
+
111
+ - Input
112
+
113
+ ```python
114
+ from payme import Payme
115
+
116
+ payme = Payme(payme_id="your-payme-id")
117
+ pay_link = payme.initializer.generate_pay_link(id=123456, amount=5000, return_url="https://example.com")
118
+ print(pay_link)
119
+ ```
120
+
121
+ - Output
122
+
123
+ ```
124
+ https://checkout.paycom.uz/bT15b3VyLXBheW1lLWlkO2FjLmlkPTEyMzQ1NjthPTUwMDAwMDtjPWh0dHBzOi8vZXhhbXBsZS5jb20=
125
+ ```
@@ -0,0 +1 @@
1
+ from payme.classes.client import Payme # noqa
@@ -0,0 +1,17 @@
1
+ from django.contrib import admin
2
+
3
+
4
+ from payme.models import PaymeTransactions
5
+
6
+
7
+ class PaymeTransactionsUI(admin.ModelAdmin):
8
+ """
9
+ Custom admin interface for PaymeTransactions model.
10
+ """
11
+ list_display = ('id', 'state', 'cancel_reason', 'created_at')
12
+ list_filter = ('state', 'cancel_reason', 'created_at')
13
+ search_fields = ('transaction_id', 'account__id')
14
+ ordering = ('-created_at',)
15
+
16
+
17
+ admin.site.register(PaymeTransactions, PaymeTransactionsUI)
@@ -1,6 +1,6 @@
1
1
  from django.apps import AppConfig
2
2
 
3
3
 
4
- class MyAppConfig(AppConfig):
4
+ class PaymeConfig(AppConfig):
5
5
  default_auto_field = 'django.db.models.BigAutoField'
6
- name = 'my_app'
6
+ name = 'payme'
@@ -0,0 +1,212 @@
1
+ from typing import Optional
2
+
3
+ from payme.util import input_type_checker
4
+ from payme.classes.http import HttpClient
5
+ from payme.types.response import cards as response
6
+
7
+
8
+ ALLOWED_METHODS = {
9
+ "cards.create": response.CardsCreateResponse,
10
+ "cards.get_verify_code": response.GetVerifyResponse,
11
+ "cards.verify": response.VerifyResponse,
12
+ "cards.remove": response.RemoveResponse,
13
+ "cards.check": response.CheckResponse
14
+ }
15
+
16
+
17
+ class Cards:
18
+ """
19
+ The Cards class provides a simple interface to interact with Paycom card
20
+ services. It allows you to create new cards and retrieve verification
21
+ codes for existing cards.
22
+ """
23
+
24
+ @input_type_checker
25
+ def __init__(self, url: str, payme_id: str) -> "Cards":
26
+ """
27
+ Initialize the Cards client.
28
+
29
+ :param payme_id: The Paycom ID used for authentication.
30
+ :param url: The base URL for the Paycom card service API.
31
+ """
32
+ headers = {
33
+ "X-Auth": payme_id,
34
+ "Content-Type": "application/json"
35
+ }
36
+ self.http = HttpClient(url, headers)
37
+
38
+ @input_type_checker
39
+ def create(self, number: str, expire: str, save: bool = False,
40
+ timeout: int = 10) -> response.CardsCreateResponse:
41
+ """
42
+ Create a new card.
43
+
44
+ :param number: The card number.
45
+ :param expire: The expiration date of the card in MMYY format.
46
+ :param save: A boolean indicating whether to save the card for future
47
+ use (default is False).
48
+ :param timeout: The request timeout duration in seconds (default is
49
+ 10 seconds).
50
+ :return: A CardsCreateResponse object containing the response data.
51
+ """
52
+ method = "cards.create"
53
+ params = {"card": {"number": number, "expire": expire}, "save": save}
54
+ return self._post_request(method, params, timeout)
55
+
56
+ @input_type_checker
57
+ def get_verify_code(self, token: str, timeout: int = 10) -> \
58
+ response.GetVerifyResponse:
59
+ """
60
+ Retrieve a verification code for a specified token.
61
+
62
+ :param token: The token associated with the card.
63
+ :param timeout: The request timeout duration in seconds (default is
64
+ 10 seconds).
65
+ :return: A GetVerifyResponse object containing the response data.
66
+ """
67
+ method = "cards.get_verify_code"
68
+ params = {"token": token}
69
+ return self._post_request(method, params, timeout)
70
+
71
+ @input_type_checker
72
+ def verify(self, token: str, code: str, timeout: int = 10) -> \
73
+ response.VerifyResponse:
74
+ """
75
+ Verify a verification code for a specified token.
76
+
77
+ :param token: The token associated with the card.
78
+ :param code: The verification code to be verified.
79
+ :param timeout: The request timeout duration in seconds (default is
80
+ 10 seconds).
81
+ :return: A VerifyResponse object containing the response data.
82
+ """
83
+ method = "cards.verify"
84
+ params = {"token": token, "code": code}
85
+ return self._post_request(method, params, timeout)
86
+
87
+ @input_type_checker
88
+ def remove(self, token: str, timeout: int = 10) -> response.RemoveResponse:
89
+ """
90
+ Remove a card from the Paycom system.
91
+
92
+ :param token: The token associated with the card.
93
+ :param timeout: The request timeout duration in seconds (default is
94
+ 10 seconds).
95
+ :return: A RemoveResponse object containing the response data.
96
+ """
97
+ method = "cards.remove"
98
+ params = {"token": token}
99
+ return self._post_request(method, params, timeout)
100
+
101
+ @input_type_checker
102
+ def check(self, token: str, timeout: int = 10) -> response.CheckResponse:
103
+ """
104
+ Check the status of a card.
105
+
106
+ :param token: The token associated with the card.
107
+ :param timeout: The request timeout duration in seconds (default is
108
+ 10 seconds).
109
+ :return: A CheckResponse object containing the response data.
110
+ """
111
+ method = "cards.check"
112
+ params = {"token": token}
113
+ return self._post_request(method, params, timeout)
114
+
115
+ @input_type_checker
116
+ def _post_request(self, method: str, params: dict,
117
+ timeout: int = 10) -> response.Common:
118
+ """
119
+ Helper method to post requests to the HTTP client.
120
+
121
+ :param method: The API method to be called.
122
+ :param params: The parameters to be sent with the request.
123
+ :param timeout: The request timeout duration in seconds (default is
124
+ 10 seconds).
125
+ :return: A response object corresponding to the method called.
126
+ """
127
+ json = {"method": method, "params": params}
128
+ dict_result = self.http.post(json, timeout)
129
+ response_class = ALLOWED_METHODS[method]
130
+ return response_class.from_dict(dict_result)
131
+
132
+ def test(self):
133
+ """
134
+ Run a comprehensive test suite for card functionalities including
135
+ creation, verification, status check, and removal.
136
+ """
137
+ # Expected values for verification
138
+ number = "8600495473316478"
139
+ expire = "0399"
140
+
141
+ expected_number = "860049******6478"
142
+ expected_expire = "03/99"
143
+ verify_code = "666666"
144
+
145
+ # Step 1: Create Card
146
+ create_response = self.create(number=number, expire=expire)
147
+ token = create_response.result.card.token
148
+
149
+ # Validate card creation response
150
+ self._assert_and_print(
151
+ create_response.result.card.number == expected_number,
152
+ "Card number matched.",
153
+ test_case="Card Creation - Number Validation"
154
+ )
155
+ self._assert_and_print(
156
+ create_response.result.card.expire == expected_expire,
157
+ "Expiration date matched.",
158
+ test_case="Card Creation - Expiration Date Validation"
159
+ )
160
+
161
+ # Step 2: Get Verification Code
162
+ get_verify_response = self.get_verify_code(token=token)
163
+ self._assert_and_print(
164
+ get_verify_response.result.sent is True,
165
+ "Verification code requested successfully.",
166
+ test_case="Verification Code Request"
167
+ )
168
+
169
+ # Step 3: Verify Code
170
+ verify_response = self.verify(token=token, code=verify_code)
171
+ self._assert_and_print(
172
+ verify_response.result.card.verify is True,
173
+ "Verification code validated successfully.",
174
+ test_case="Code Verification"
175
+ )
176
+
177
+ # Step 4: Check Card Status
178
+ check_response = self.check(token=token)
179
+ self._assert_and_print(
180
+ check_response.result.card.verify is True,
181
+ "Card status verified successfully.",
182
+ test_case="Card Status Check"
183
+ )
184
+
185
+ # Step 5: Remove Card
186
+ remove_response = self.remove(token=token)
187
+ self._assert_and_print(
188
+ remove_response.result.success is True,
189
+ "Card removed successfully.",
190
+ test_case="Card Removal"
191
+ )
192
+
193
+ def _assert_and_print(self, condition: bool, success_message: str,
194
+ test_case: Optional[str] = None):
195
+ """
196
+ Assertion helper that prints success or failure messages based on
197
+ test outcomes.
198
+
199
+ :param condition: The test condition to check.
200
+ :param success_message: Message to print upon successful test.
201
+ :param test_case: A description of the test case (optional).
202
+ """
203
+ try:
204
+ assert condition, "Assertion failed!"
205
+ print(f"Success: {success_message}")
206
+ except AssertionError as exc:
207
+ error_message = (
208
+ f"Test Case Failed: {test_case or 'Unknown Test Case'}\n"
209
+ f"Error Details: {str(exc)}"
210
+ )
211
+ print(error_message)
212
+ raise AssertionError(error_message) from exc
@@ -0,0 +1,31 @@
1
+
2
+ from typing import Union
3
+
4
+ from payme.const import Networks
5
+ from payme.classes.cards import Cards
6
+ from payme.util import input_type_checker
7
+ from payme.classes.receipts import Receipts
8
+ from payme.classes.initializer import Initializer
9
+
10
+
11
+ class Payme:
12
+ """
13
+ The payme class provides a simple interface
14
+ """
15
+ @input_type_checker
16
+ def __init__(
17
+ self,
18
+ payme_id: str,
19
+ payme_key: Union[str, None] = None,
20
+ is_test_mode: bool = False
21
+ ):
22
+
23
+ # initialize payme network
24
+ url = Networks.PROD_NET
25
+
26
+ if is_test_mode is True:
27
+ url = Networks.TEST_NET
28
+
29
+ self.cards = Cards(url=url, payme_id=payme_id)
30
+ self.initializer = Initializer(payme_id=payme_id)
31
+ self.receipts = Receipts(url=url, payme_id=payme_id, payme_key=payme_key) # noqa
@@ -0,0 +1,106 @@
1
+ import requests
2
+
3
+ from payme.exceptions import general as exc
4
+
5
+
6
+ networking_errors = (
7
+ requests.exceptions.Timeout,
8
+ requests.exceptions.HTTPError,
9
+ requests.exceptions.ConnectionError,
10
+ requests.exceptions.TooManyRedirects,
11
+ requests.exceptions.URLRequired,
12
+ requests.exceptions.MissingSchema,
13
+ requests.exceptions.InvalidURL,
14
+ requests.exceptions.InvalidHeader,
15
+ requests.exceptions.JSONDecodeError,
16
+ requests.exceptions.ConnectTimeout,
17
+ requests.exceptions.ReadTimeout,
18
+ requests.exceptions.SSLError,
19
+ requests.exceptions.ProxyError,
20
+ requests.exceptions.ChunkedEncodingError,
21
+ requests.exceptions.StreamConsumedError,
22
+ requests.exceptions.RequestException
23
+ )
24
+
25
+
26
+ class HttpClient:
27
+ """
28
+ A simple HTTP client to handle requests to a specified URL.
29
+ It provides methods for sending GET, POST, PUT, and DELETE requests
30
+ with error handling.
31
+ """
32
+
33
+ def __init__(self, url: str, headers: dict = None):
34
+ """
35
+ Initialize the HttpClient.
36
+
37
+ Parameters
38
+ ----------
39
+ url : str
40
+ The base URL for the API (e.g., 'https://checkout.paycom.uz/api').
41
+ headers : dict, optional
42
+ Optional default headers to include in all requests.
43
+ These headers will be sent with every request unless overridden.
44
+ """
45
+ self.url = url
46
+ self.headers = headers
47
+
48
+ def post(self, json: dict, timeout: int = 10):
49
+ """
50
+ Send a POST request to the specified URL with the provided JSON data.
51
+
52
+ Parameters
53
+ ----------
54
+ json : dict
55
+ The JSON data payload for the POST request. This will be sent
56
+ as the request body.
57
+ timeout : int, optional
58
+ The request timeout duration in seconds (default is 10 seconds).
59
+
60
+ Returns
61
+ -------
62
+ dict
63
+ A dictionary containing the response data if the request was
64
+ successful, or an error message if an error occurred.
65
+ """
66
+ try:
67
+ response = requests.post(
68
+ url=self.url,
69
+ headers=self.headers,
70
+ json=json,
71
+ timeout=timeout
72
+ )
73
+ response.raise_for_status()
74
+ response_data = response.json()
75
+
76
+ # Check if the response contains a specific error format
77
+ if "error" in response_data:
78
+ return self.handle_payme_error(response_data["error"])
79
+
80
+ return response_data
81
+
82
+ except networking_errors as exc_data:
83
+ raise exc.PaymeNetworkError(data=exc_data)
84
+
85
+ def handle_payme_error(self, error: dict):
86
+ """
87
+ Handle Paycom-specific errors from the JSON-RPC error response.
88
+
89
+ Parameters
90
+ ----------
91
+ error : dict
92
+ The error dictionary from Paycom's response, typically containing
93
+ error details such as code, message, and data.
94
+
95
+ Returns
96
+ -------
97
+ None
98
+ Raises an exception based on the error code received from
99
+ Paycom's response.
100
+ """
101
+ error_code = error.get("code", "Unknown code")
102
+ error_message = error.get("message", "Unknown error")
103
+ error_data = error.get("data", "")
104
+
105
+ exception_class = exc.errors_map.get(error_code, exc.BaseError)
106
+ raise exception_class(message=error_message, data=error_data)
@@ -0,0 +1,77 @@
1
+ import base64
2
+
3
+ from payme.util import input_type_checker
4
+
5
+
6
+ class Initializer:
7
+ """
8
+ Initialize the Payme class with necessary details.
9
+
10
+ Attributes
11
+ ----------
12
+ payme_id: str
13
+ The Payme ID associated with your account
14
+ """
15
+
16
+ @input_type_checker
17
+ def __init__(self, payme_id: str = None):
18
+ self.payme_id = payme_id
19
+
20
+ # pylint: disable=W0622
21
+ @input_type_checker
22
+ def generate_pay_link(
23
+ self,
24
+ id: int,
25
+ amount: int,
26
+ return_url: str
27
+ ) -> str:
28
+ """
29
+ Generate a payment link for a specific order.
30
+
31
+ This method encodes the payment parameters into a base64 string and
32
+ constructs a URL for the Payme checkout.
33
+
34
+ Parameters
35
+ ----------
36
+ id : int
37
+ Unique identifier for the account.
38
+ amount : int
39
+ The amount associated with the order in currency units.
40
+ return_url : str
41
+ The URL to which the user will be redirected after the payment is
42
+ processed.
43
+
44
+ Returns
45
+ -------
46
+ str
47
+ A payment link formatted as a URL, ready to be used in the payment
48
+ process.
49
+
50
+ References
51
+ ----------
52
+ For full method documentation, visit:
53
+ https://developer.help.paycom.uz/initsializatsiya-platezhey/
54
+ """
55
+ amount = amount * 100 # Convert amount to the smallest currency unit
56
+ params = (
57
+ f'm={self.payme_id};ac.id={id};a={amount};c={return_url}'
58
+ )
59
+ params = base64.b64encode(params.encode("utf-8")).decode("utf-8")
60
+ return f"https://checkout.paycom.uz/{params}"
61
+
62
+ def test(self):
63
+ """
64
+ Test method for the Initializer class.
65
+
66
+ This method generates a payment link for a sample order and checks
67
+ if the result is a valid string. If successful, it prints a
68
+ confirmation message.
69
+ """
70
+ result = self.generate_pay_link(
71
+ id=12345,
72
+ amount=7000,
73
+ return_url="https://example.com"
74
+ )
75
+
76
+ assert isinstance(result, str), "Failed to generate payment link"
77
+ print("Success: Payment link generated successfully.")