kobil-payment 1.2.0__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.
@@ -0,0 +1,53 @@
1
+ Metadata-Version: 2.4
2
+ Name: kobil-payment
3
+ Version: 1.2.0
4
+ Summary: KOBIL Pay (mpay-merchant) client for Python with automatic OAuth token management.
5
+ License: MIT
6
+ Project-URL: Repository, https://github.com/uveysservetoglu/kobil-sdks
7
+ Keywords: kobil,payment,mpay,oauth2
8
+ Requires-Python: >=3.8
9
+ Description-Content-Type: text/markdown
10
+ Requires-Dist: kobil-core>=1.0
11
+
12
+ # kobil-payment
13
+
14
+ KOBIL Pay (mpay-merchant) client for Python, with automatic OAuth token management.
15
+
16
+ ```bash
17
+ pip install kobil-payment
18
+ ```
19
+
20
+ Credentials are shared across modules and read from `KOBIL_*` env vars if omitted.
21
+ `merchant_id` defaults to `client_id`. Amounts are in the smallest currency unit
22
+ (`1300` = 13.00 EUR); timeouts in minutes.
23
+
24
+ ```python
25
+ from kobil.payment import PaymentClient, payment_group
26
+
27
+ payment = PaymentClient(
28
+ payment_base_url="https://pay.cloud.kobil.com/mpay-merchant/create/transaction",
29
+ merchant_name="ISPARK",
30
+ # credentials optional if KOBIL_* env vars are set:
31
+ client_id="...", client_secret="...", token_endpoint="https://idp/token",
32
+ )
33
+
34
+ res = payment.create_transaction(
35
+ user_id=user_id,
36
+ amount=1300,
37
+ payment_content=payment_group(("Service Amount", "10.0 TL"), ("Tax Amount", "3.0 TL")),
38
+ )
39
+ # res["transactionId"], res["status"]
40
+
41
+ payment.create_pre_auth_transaction(user_id, 1300)
42
+ payment.post_auth(transaction_id, 40)
43
+ payment.get_status(transaction_id)
44
+ payment.cancel(transaction_id, user_id, cancellation_message="Iptal")
45
+ payment.refund(transaction_id, user_id, 5555, currency="USD")
46
+ ```
47
+
48
+ Each operation returns the decoded response dict. Failures raise
49
+ `kobil.payment.KobilPaymentError` (subclass of `kobil.core.KobilError`).
50
+
51
+ ## License
52
+
53
+ MIT
@@ -0,0 +1,42 @@
1
+ # kobil-payment
2
+
3
+ KOBIL Pay (mpay-merchant) client for Python, with automatic OAuth token management.
4
+
5
+ ```bash
6
+ pip install kobil-payment
7
+ ```
8
+
9
+ Credentials are shared across modules and read from `KOBIL_*` env vars if omitted.
10
+ `merchant_id` defaults to `client_id`. Amounts are in the smallest currency unit
11
+ (`1300` = 13.00 EUR); timeouts in minutes.
12
+
13
+ ```python
14
+ from kobil.payment import PaymentClient, payment_group
15
+
16
+ payment = PaymentClient(
17
+ payment_base_url="https://pay.cloud.kobil.com/mpay-merchant/create/transaction",
18
+ merchant_name="ISPARK",
19
+ # credentials optional if KOBIL_* env vars are set:
20
+ client_id="...", client_secret="...", token_endpoint="https://idp/token",
21
+ )
22
+
23
+ res = payment.create_transaction(
24
+ user_id=user_id,
25
+ amount=1300,
26
+ payment_content=payment_group(("Service Amount", "10.0 TL"), ("Tax Amount", "3.0 TL")),
27
+ )
28
+ # res["transactionId"], res["status"]
29
+
30
+ payment.create_pre_auth_transaction(user_id, 1300)
31
+ payment.post_auth(transaction_id, 40)
32
+ payment.get_status(transaction_id)
33
+ payment.cancel(transaction_id, user_id, cancellation_message="Iptal")
34
+ payment.refund(transaction_id, user_id, 5555, currency="USD")
35
+ ```
36
+
37
+ Each operation returns the decoded response dict. Failures raise
38
+ `kobil.payment.KobilPaymentError` (subclass of `kobil.core.KobilError`).
39
+
40
+ ## License
41
+
42
+ MIT
@@ -0,0 +1,187 @@
1
+ """kobil.payment — KOBIL Pay (mpay-merchant) client."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import urllib.parse
6
+ from typing import Any, Dict, List, Optional, Sequence, Tuple
7
+
8
+ from kobil.core import (
9
+ DefaultTokenProvider,
10
+ KobilError,
11
+ ServiceClient,
12
+ TokenProvider,
13
+ credentials_from_env,
14
+ new_uuid,
15
+ )
16
+
17
+ __all__ = ["PaymentClient", "KobilPaymentError", "payment_group"]
18
+
19
+
20
+ class KobilPaymentError(KobilError):
21
+ """Thrown when a payment operation fails."""
22
+
23
+
24
+ def payment_group(*items: Tuple[str, Any]) -> List[List[Dict[str, Any]]]:
25
+ """Builds a single group of key/value lines.
26
+
27
+ Example: payment_group(("Service Amount", "10.0 TL"), ("Tax Amount", "3.0 TL"))
28
+ """
29
+ return [[{"key": key, "value": value} for key, value in items]]
30
+
31
+
32
+ class PaymentClient(ServiceClient):
33
+ def __init__(
34
+ self,
35
+ *,
36
+ payment_base_url: str,
37
+ merchant_name: str,
38
+ token_endpoint: Optional[str] = None,
39
+ client_id: Optional[str] = None,
40
+ client_secret: Optional[str] = None,
41
+ token_auth_mode: Optional[str] = None,
42
+ merchant_id: Optional[str] = None,
43
+ merchant_service_uuid: Optional[str] = None,
44
+ tenant_id: Optional[str] = None,
45
+ default_currency: str = "EUR",
46
+ default_merchant_callback: Optional[str] = None,
47
+ default_transaction_timeout_minutes: int = 59,
48
+ version: int = 1,
49
+ token_provider: Optional[TokenProvider] = None,
50
+ ) -> None:
51
+ credentials = credentials_from_env(
52
+ token_endpoint=token_endpoint,
53
+ client_id=client_id,
54
+ client_secret=client_secret,
55
+ token_auth_mode=token_auth_mode,
56
+ )
57
+ super().__init__(token_provider or DefaultTokenProvider(credentials))
58
+
59
+ if not payment_base_url:
60
+ raise KobilPaymentError("payment_base_url is required.")
61
+ if not merchant_name:
62
+ raise KobilPaymentError("merchant_name is required.")
63
+
64
+ self._base = payment_base_url.rstrip("/")
65
+ self._client_id = credentials.client_id
66
+ self._merchant_name = merchant_name
67
+ self._merchant_id = merchant_id
68
+ self._merchant_service_uuid = merchant_service_uuid
69
+ self._tenant_id = tenant_id
70
+ self._default_currency = default_currency
71
+ self._default_callback = default_merchant_callback
72
+ self._default_timeout = default_transaction_timeout_minutes
73
+ self._version = version
74
+
75
+ def _make_error(self, message, status_code=None, response_body=None, cause=None) -> KobilError:
76
+ return KobilPaymentError(message, status_code, response_body, cause)
77
+
78
+ def create_transaction(
79
+ self,
80
+ user_id: str,
81
+ amount: int,
82
+ payment_content: Optional[Sequence[Sequence[Dict[str, Any]]]] = None,
83
+ currency: Optional[str] = None,
84
+ merchant_callback: Optional[str] = None,
85
+ timeout_minutes: Optional[int] = None,
86
+ idempotency_id: Optional[str] = None,
87
+ ) -> Dict[str, Any]:
88
+ return self._create(False, user_id, amount, payment_content, currency, merchant_callback, timeout_minutes, idempotency_id)
89
+
90
+ def create_pre_auth_transaction(
91
+ self,
92
+ user_id: str,
93
+ amount: int,
94
+ payment_content: Optional[Sequence[Sequence[Dict[str, Any]]]] = None,
95
+ currency: Optional[str] = None,
96
+ merchant_callback: Optional[str] = None,
97
+ timeout_minutes: Optional[int] = None,
98
+ idempotency_id: Optional[str] = None,
99
+ ) -> Dict[str, Any]:
100
+ return self._create(True, user_id, amount, payment_content, currency, merchant_callback, timeout_minutes, idempotency_id)
101
+
102
+ def _create(self, pre_auth, user_id, amount, payment_content, currency, merchant_callback, timeout_minutes, idempotency_id) -> Dict[str, Any]:
103
+ if not user_id:
104
+ raise KobilPaymentError("user_id cannot be empty.")
105
+ body: Dict[str, Any] = {
106
+ "version": self._version,
107
+ "idempotencyId": idempotency_id or new_uuid(),
108
+ "userId": user_id,
109
+ "merchantId": self._resolve_merchant_id(),
110
+ "merchantServiceUUID": self._resolve_service_uuid(),
111
+ "merchantName": self._merchant_name,
112
+ "merchantCallback": merchant_callback or self._default_callback,
113
+ "transactionTimeout": timeout_minutes or self._default_timeout,
114
+ "tenantId": self._tenant_id,
115
+ "amount": amount,
116
+ "currency": (currency or self._default_currency).upper(),
117
+ "paymentContent": list(payment_content) if payment_content else None,
118
+ }
119
+ if pre_auth:
120
+ body["paymentTenantType"] = "preAuth"
121
+ return self.send_json("POST", self._base, body)
122
+
123
+ def post_auth(self, transaction_id: str, amount: int, merchant_callback: Optional[str] = None, idempotency_id: Optional[str] = None) -> Dict[str, Any]:
124
+ if not transaction_id:
125
+ raise KobilPaymentError("transaction_id cannot be empty.")
126
+ query = {
127
+ "id": transaction_id,
128
+ "idempotencyId": idempotency_id or new_uuid(),
129
+ "amount": str(amount),
130
+ }
131
+ callback = merchant_callback or self._default_callback
132
+ if callback:
133
+ query["merchantCallback"] = callback
134
+ return self.send_json("GET", f"{self._base}/postauth?{urllib.parse.urlencode(query)}")
135
+
136
+ def get_status(self, transaction_id: str, merchant_callback: Optional[str] = None) -> Dict[str, Any]:
137
+ if not transaction_id:
138
+ raise KobilPaymentError("transaction_id cannot be empty.")
139
+ return self.send_json("POST", f"{self._base}/status", {
140
+ "merchantId": self._resolve_merchant_id(),
141
+ "merchantCallback": merchant_callback or self._default_callback,
142
+ "transactionId": transaction_id,
143
+ })
144
+
145
+ def cancel(self, transaction_id: str, user_id: str, cancellation_message: Optional[str] = None,
146
+ merchant_callback: Optional[str] = None, timeout_minutes: Optional[int] = None,
147
+ idempotency_id: Optional[str] = None) -> Dict[str, Any]:
148
+ if not transaction_id or not user_id:
149
+ raise KobilPaymentError("transaction_id and user_id are required.")
150
+ return self.send_json("POST", f"{self._base}/void", {
151
+ "version": self._version,
152
+ "userId": user_id,
153
+ "idempotencyId": idempotency_id or new_uuid(),
154
+ "merchantServiceUUID": self._resolve_service_uuid(),
155
+ "merchantCallback": merchant_callback or self._default_callback,
156
+ "transactionTimeout": timeout_minutes or self._default_timeout,
157
+ "merchantId": self._resolve_merchant_id(),
158
+ "paymentTransactionId": transaction_id,
159
+ "cancellationMessage": cancellation_message,
160
+ })
161
+
162
+ def refund(self, transaction_id: str, user_id: str, amount: int, currency: Optional[str] = None,
163
+ cancellation_message: Optional[str] = None, merchant_callback: Optional[str] = None,
164
+ timeout_minutes: Optional[int] = None, idempotency_id: Optional[str] = None) -> Dict[str, Any]:
165
+ if not transaction_id or not user_id:
166
+ raise KobilPaymentError("transaction_id and user_id are required.")
167
+ service_uuid = self._resolve_service_uuid()
168
+ return self.send_json("POST", f"{self._base}/refund", {
169
+ "version": self._version,
170
+ "userId": user_id,
171
+ "idempotencyId": idempotency_id or new_uuid(),
172
+ "merchantServiceUUID": service_uuid,
173
+ "merchantCallback": merchant_callback or self._default_callback,
174
+ "transactionTimeout": timeout_minutes or self._default_timeout,
175
+ "merchantId": self._resolve_merchant_id(),
176
+ "merchantUserId": user_id,
177
+ "paymentTransactionId": transaction_id,
178
+ "amount": amount,
179
+ "currency": (currency or self._default_currency).upper(),
180
+ "merchantServiceProviderId": service_uuid,
181
+ })
182
+
183
+ def _resolve_merchant_id(self) -> str:
184
+ return self._merchant_id or self._client_id
185
+
186
+ def _resolve_service_uuid(self) -> str:
187
+ return self._merchant_service_uuid or self._resolve_merchant_id()
@@ -0,0 +1,53 @@
1
+ Metadata-Version: 2.4
2
+ Name: kobil-payment
3
+ Version: 1.2.0
4
+ Summary: KOBIL Pay (mpay-merchant) client for Python with automatic OAuth token management.
5
+ License: MIT
6
+ Project-URL: Repository, https://github.com/uveysservetoglu/kobil-sdks
7
+ Keywords: kobil,payment,mpay,oauth2
8
+ Requires-Python: >=3.8
9
+ Description-Content-Type: text/markdown
10
+ Requires-Dist: kobil-core>=1.0
11
+
12
+ # kobil-payment
13
+
14
+ KOBIL Pay (mpay-merchant) client for Python, with automatic OAuth token management.
15
+
16
+ ```bash
17
+ pip install kobil-payment
18
+ ```
19
+
20
+ Credentials are shared across modules and read from `KOBIL_*` env vars if omitted.
21
+ `merchant_id` defaults to `client_id`. Amounts are in the smallest currency unit
22
+ (`1300` = 13.00 EUR); timeouts in minutes.
23
+
24
+ ```python
25
+ from kobil.payment import PaymentClient, payment_group
26
+
27
+ payment = PaymentClient(
28
+ payment_base_url="https://pay.cloud.kobil.com/mpay-merchant/create/transaction",
29
+ merchant_name="ISPARK",
30
+ # credentials optional if KOBIL_* env vars are set:
31
+ client_id="...", client_secret="...", token_endpoint="https://idp/token",
32
+ )
33
+
34
+ res = payment.create_transaction(
35
+ user_id=user_id,
36
+ amount=1300,
37
+ payment_content=payment_group(("Service Amount", "10.0 TL"), ("Tax Amount", "3.0 TL")),
38
+ )
39
+ # res["transactionId"], res["status"]
40
+
41
+ payment.create_pre_auth_transaction(user_id, 1300)
42
+ payment.post_auth(transaction_id, 40)
43
+ payment.get_status(transaction_id)
44
+ payment.cancel(transaction_id, user_id, cancellation_message="Iptal")
45
+ payment.refund(transaction_id, user_id, 5555, currency="USD")
46
+ ```
47
+
48
+ Each operation returns the decoded response dict. Failures raise
49
+ `kobil.payment.KobilPaymentError` (subclass of `kobil.core.KobilError`).
50
+
51
+ ## License
52
+
53
+ MIT
@@ -0,0 +1,8 @@
1
+ README.md
2
+ pyproject.toml
3
+ kobil/payment/__init__.py
4
+ kobil_payment.egg-info/PKG-INFO
5
+ kobil_payment.egg-info/SOURCES.txt
6
+ kobil_payment.egg-info/dependency_links.txt
7
+ kobil_payment.egg-info/requires.txt
8
+ kobil_payment.egg-info/top_level.txt
@@ -0,0 +1 @@
1
+ kobil-core>=1.0
@@ -0,0 +1,20 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "kobil-payment"
7
+ version = "1.2.0"
8
+ description = "KOBIL Pay (mpay-merchant) client for Python with automatic OAuth token management."
9
+ readme = "README.md"
10
+ license = { text = "MIT" }
11
+ requires-python = ">=3.8"
12
+ keywords = ["kobil", "payment", "mpay", "oauth2"]
13
+ dependencies = ["kobil-core>=1.0"]
14
+
15
+ [project.urls]
16
+ Repository = "https://github.com/uveysservetoglu/kobil-sdks"
17
+
18
+ [tool.setuptools.packages.find]
19
+ include = ["kobil*"]
20
+ namespaces = true
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+