snippe 0.1.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,6 @@
1
+ {
2
+ "disabledMcpjsonServers": [
3
+ "shadcn",
4
+ "icons8mcp"
5
+ ]
6
+ }
@@ -0,0 +1,2 @@
1
+ .venv
2
+ sdk.md
snippe-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,249 @@
1
+ Metadata-Version: 2.4
2
+ Name: snippe
3
+ Version: 0.1.0
4
+ Summary: Official Python SDK for Snippe Payment API
5
+ Project-URL: Homepage, https://snippe.sh
6
+ Project-URL: Documentation, https://documenter.getpostman.com/view/36488510/2sBXViiWAV#6beb6d54-34a1-4c9c-8a19-acd92a865711
7
+ Project-URL: Repository, https://github.com/Neurotech-HQ/snippe-python-sdk
8
+ Author-email: Nassdaq <mwaijegakelvin@gmail.com>
9
+ License-Expression: MIT
10
+ Keywords: Tanzania Payment,africa,fintech,mobile-money,snippe
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.8
16
+ Classifier: Programming Language :: Python :: 3.9
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
21
+ Requires-Python: >=3.10
22
+ Requires-Dist: httpx>=0.24.0
23
+ Provides-Extra: dev
24
+ Requires-Dist: pytest-asyncio>=0.21.0; extra == 'dev'
25
+ Requires-Dist: pytest>=7.0.0; extra == 'dev'
26
+ Requires-Dist: respx>=0.20.0; extra == 'dev'
27
+ Description-Content-Type: text/markdown
28
+
29
+ # Snippe Python SDK
30
+
31
+ Official Python SDK for [Snippe Payment API](https://snippe.sh) - Accept payments via mobile money, card, and QR code in East Africa.
32
+
33
+ ## Installation
34
+
35
+ ```bash
36
+ pip install snippe
37
+ ```
38
+
39
+ ## Quick Start
40
+
41
+ ```python
42
+ from snippe import Snippe, Customer
43
+
44
+ client = Snippe("your_api_key")
45
+
46
+ # Create a mobile money payment
47
+ payment = client.create_mobile_payment(
48
+ amount=1000,
49
+ currency="TZS",
50
+ phone_number="0788500000",
51
+ customer=Customer(firstname="John", lastname="Doe"),
52
+ )
53
+
54
+ print(f"Payment reference: {payment.reference}")
55
+ print(f"Status: {payment.status}")
56
+ ```
57
+
58
+ ## Payment Types
59
+
60
+ ### Mobile Money (USSD Push)
61
+
62
+ Customer receives a USSD prompt on their phone to confirm payment.
63
+
64
+ ```python
65
+ payment = client.create_mobile_payment(
66
+ amount=5000,
67
+ currency="TZS",
68
+ phone_number="0712345678",
69
+ customer=Customer(
70
+ firstname="Jane",
71
+ lastname="Doe",
72
+ email="jane@example.com" # optional
73
+ ),
74
+ webhook_url="https://yourapp.com/webhooks", # optional
75
+ metadata={"order_id": "ORD-123"}, # optional
76
+ )
77
+ ```
78
+
79
+ ### Card Payment
80
+
81
+ Returns a `payment_url` to redirect the customer to complete payment.
82
+
83
+ ```python
84
+ payment = client.create_card_payment(
85
+ amount=50000,
86
+ currency="TZS",
87
+ phone_number="0712345678",
88
+ customer=Customer(
89
+ firstname="John",
90
+ lastname="Doe",
91
+ email="john@example.com",
92
+ address="123 Main Street",
93
+ city="Dar es Salaam",
94
+ state="DSM",
95
+ postcode="14101",
96
+ country="TZ",
97
+ ),
98
+ callback_url="https://yourapp.com/callback", # required for card
99
+ webhook_url="https://yourapp.com/webhooks",
100
+ )
101
+
102
+ # Redirect customer to this URL
103
+ print(payment.payment_url)
104
+ ```
105
+
106
+ ### QR Code Payment
107
+
108
+ Returns a QR code for the customer to scan.
109
+
110
+ ```python
111
+ payment = client.create_qr_payment(
112
+ amount=25000,
113
+ currency="TZS",
114
+ phone_number="0712345678",
115
+ customer=Customer(firstname="John", lastname="Doe"),
116
+ )
117
+
118
+ # Display this QR code to customer
119
+ print(payment.payment_qr_code)
120
+ print(payment.payment_token)
121
+ ```
122
+
123
+ ## Check Payment Status
124
+
125
+ ```python
126
+ payment = client.get_payment("payment_reference")
127
+ print(f"Status: {payment.status}") # pending, completed, failed, expired, voided
128
+ ```
129
+
130
+ ## List Payments
131
+
132
+ ```python
133
+ result = client.list_payments(limit=20, offset=0)
134
+ for payment in result.payments:
135
+ print(f"{payment.reference}: {payment.status}")
136
+ ```
137
+
138
+ ## Check Balance
139
+
140
+ ```python
141
+ balance = client.get_balance()
142
+ print(f"Available: {balance.available_balance} {balance.currency}")
143
+ ```
144
+
145
+ ## Webhooks
146
+
147
+ Verify and parse webhook events from Snippe.
148
+
149
+ ```python
150
+ from snippe import verify_webhook, WebhookVerificationError
151
+
152
+ # In your webhook endpoint
153
+ try:
154
+ payload = verify_webhook(
155
+ body=request.body.decode(),
156
+ signature=request.headers["X-Webhook-Signature"],
157
+ timestamp=request.headers["X-Webhook-Timestamp"],
158
+ signing_key="your_webhook_signing_key",
159
+ )
160
+
161
+ if payload.event == "payment.completed":
162
+ print(f"Payment {payload.reference} completed!")
163
+ # Fulfill the order
164
+ elif payload.event == "payment.failed":
165
+ print(f"Payment {payload.reference} failed")
166
+ # Notify customer
167
+
168
+ except WebhookVerificationError as e:
169
+ print(f"Invalid webhook: {e}")
170
+ ```
171
+
172
+ ### Webhook Events
173
+
174
+ | Event | Description |
175
+ |-------|-------------|
176
+ | `payment.completed` | Payment successful |
177
+ | `payment.failed` | Payment declined or failed |
178
+ | `payment.expired` | Payment timed out |
179
+ | `payment.voided` | Payment cancelled |
180
+
181
+ ## Async Support
182
+
183
+ For async applications (FastAPI, aiohttp, etc.):
184
+
185
+ ```python
186
+ from snippe import AsyncSnippe, Customer
187
+
188
+ async def create_payment():
189
+ async with AsyncSnippe("your_api_key") as client:
190
+ payment = await client.create_mobile_payment(
191
+ amount=1000,
192
+ currency="TZS",
193
+ phone_number="0788500000",
194
+ customer=Customer(firstname="John", lastname="Doe"),
195
+ )
196
+ return payment
197
+ ```
198
+
199
+ ## Idempotency
200
+
201
+ Prevent duplicate payments by providing an idempotency key:
202
+
203
+ ```python
204
+ payment = client.create_mobile_payment(
205
+ amount=1000,
206
+ currency="TZS",
207
+ phone_number="0788500000",
208
+ customer=Customer(firstname="John", lastname="Doe"),
209
+ idempotency_key="unique_order_id_123", # Your unique identifier
210
+ )
211
+ ```
212
+
213
+ ## Error Handling
214
+
215
+ ```python
216
+ from snippe import (
217
+ Snippe,
218
+ AuthenticationError,
219
+ ValidationError,
220
+ NotFoundError,
221
+ RateLimitError,
222
+ ServerError,
223
+ )
224
+
225
+ try:
226
+ payment = client.create_mobile_payment(...)
227
+ except AuthenticationError:
228
+ print("Invalid API key")
229
+ except ValidationError as e:
230
+ print(f"Invalid request: {e.message}")
231
+ except NotFoundError:
232
+ print("Payment not found")
233
+ except RateLimitError:
234
+ print("Too many requests, slow down")
235
+ except ServerError:
236
+ print("Snippe server error, try again later")
237
+ ```
238
+
239
+ ## Supported Currencies
240
+
241
+ | Currency | Country |
242
+ |----------|---------|
243
+ | TZS | Tanzania |
244
+ | KES | Kenya |
245
+ | UGX | Uganda |
246
+
247
+ ## License
248
+
249
+ MIT
snippe-0.1.0/README.md ADDED
@@ -0,0 +1,221 @@
1
+ # Snippe Python SDK
2
+
3
+ Official Python SDK for [Snippe Payment API](https://snippe.sh) - Accept payments via mobile money, card, and QR code in East Africa.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ pip install snippe
9
+ ```
10
+
11
+ ## Quick Start
12
+
13
+ ```python
14
+ from snippe import Snippe, Customer
15
+
16
+ client = Snippe("your_api_key")
17
+
18
+ # Create a mobile money payment
19
+ payment = client.create_mobile_payment(
20
+ amount=1000,
21
+ currency="TZS",
22
+ phone_number="0788500000",
23
+ customer=Customer(firstname="John", lastname="Doe"),
24
+ )
25
+
26
+ print(f"Payment reference: {payment.reference}")
27
+ print(f"Status: {payment.status}")
28
+ ```
29
+
30
+ ## Payment Types
31
+
32
+ ### Mobile Money (USSD Push)
33
+
34
+ Customer receives a USSD prompt on their phone to confirm payment.
35
+
36
+ ```python
37
+ payment = client.create_mobile_payment(
38
+ amount=5000,
39
+ currency="TZS",
40
+ phone_number="0712345678",
41
+ customer=Customer(
42
+ firstname="Jane",
43
+ lastname="Doe",
44
+ email="jane@example.com" # optional
45
+ ),
46
+ webhook_url="https://yourapp.com/webhooks", # optional
47
+ metadata={"order_id": "ORD-123"}, # optional
48
+ )
49
+ ```
50
+
51
+ ### Card Payment
52
+
53
+ Returns a `payment_url` to redirect the customer to complete payment.
54
+
55
+ ```python
56
+ payment = client.create_card_payment(
57
+ amount=50000,
58
+ currency="TZS",
59
+ phone_number="0712345678",
60
+ customer=Customer(
61
+ firstname="John",
62
+ lastname="Doe",
63
+ email="john@example.com",
64
+ address="123 Main Street",
65
+ city="Dar es Salaam",
66
+ state="DSM",
67
+ postcode="14101",
68
+ country="TZ",
69
+ ),
70
+ callback_url="https://yourapp.com/callback", # required for card
71
+ webhook_url="https://yourapp.com/webhooks",
72
+ )
73
+
74
+ # Redirect customer to this URL
75
+ print(payment.payment_url)
76
+ ```
77
+
78
+ ### QR Code Payment
79
+
80
+ Returns a QR code for the customer to scan.
81
+
82
+ ```python
83
+ payment = client.create_qr_payment(
84
+ amount=25000,
85
+ currency="TZS",
86
+ phone_number="0712345678",
87
+ customer=Customer(firstname="John", lastname="Doe"),
88
+ )
89
+
90
+ # Display this QR code to customer
91
+ print(payment.payment_qr_code)
92
+ print(payment.payment_token)
93
+ ```
94
+
95
+ ## Check Payment Status
96
+
97
+ ```python
98
+ payment = client.get_payment("payment_reference")
99
+ print(f"Status: {payment.status}") # pending, completed, failed, expired, voided
100
+ ```
101
+
102
+ ## List Payments
103
+
104
+ ```python
105
+ result = client.list_payments(limit=20, offset=0)
106
+ for payment in result.payments:
107
+ print(f"{payment.reference}: {payment.status}")
108
+ ```
109
+
110
+ ## Check Balance
111
+
112
+ ```python
113
+ balance = client.get_balance()
114
+ print(f"Available: {balance.available_balance} {balance.currency}")
115
+ ```
116
+
117
+ ## Webhooks
118
+
119
+ Verify and parse webhook events from Snippe.
120
+
121
+ ```python
122
+ from snippe import verify_webhook, WebhookVerificationError
123
+
124
+ # In your webhook endpoint
125
+ try:
126
+ payload = verify_webhook(
127
+ body=request.body.decode(),
128
+ signature=request.headers["X-Webhook-Signature"],
129
+ timestamp=request.headers["X-Webhook-Timestamp"],
130
+ signing_key="your_webhook_signing_key",
131
+ )
132
+
133
+ if payload.event == "payment.completed":
134
+ print(f"Payment {payload.reference} completed!")
135
+ # Fulfill the order
136
+ elif payload.event == "payment.failed":
137
+ print(f"Payment {payload.reference} failed")
138
+ # Notify customer
139
+
140
+ except WebhookVerificationError as e:
141
+ print(f"Invalid webhook: {e}")
142
+ ```
143
+
144
+ ### Webhook Events
145
+
146
+ | Event | Description |
147
+ |-------|-------------|
148
+ | `payment.completed` | Payment successful |
149
+ | `payment.failed` | Payment declined or failed |
150
+ | `payment.expired` | Payment timed out |
151
+ | `payment.voided` | Payment cancelled |
152
+
153
+ ## Async Support
154
+
155
+ For async applications (FastAPI, aiohttp, etc.):
156
+
157
+ ```python
158
+ from snippe import AsyncSnippe, Customer
159
+
160
+ async def create_payment():
161
+ async with AsyncSnippe("your_api_key") as client:
162
+ payment = await client.create_mobile_payment(
163
+ amount=1000,
164
+ currency="TZS",
165
+ phone_number="0788500000",
166
+ customer=Customer(firstname="John", lastname="Doe"),
167
+ )
168
+ return payment
169
+ ```
170
+
171
+ ## Idempotency
172
+
173
+ Prevent duplicate payments by providing an idempotency key:
174
+
175
+ ```python
176
+ payment = client.create_mobile_payment(
177
+ amount=1000,
178
+ currency="TZS",
179
+ phone_number="0788500000",
180
+ customer=Customer(firstname="John", lastname="Doe"),
181
+ idempotency_key="unique_order_id_123", # Your unique identifier
182
+ )
183
+ ```
184
+
185
+ ## Error Handling
186
+
187
+ ```python
188
+ from snippe import (
189
+ Snippe,
190
+ AuthenticationError,
191
+ ValidationError,
192
+ NotFoundError,
193
+ RateLimitError,
194
+ ServerError,
195
+ )
196
+
197
+ try:
198
+ payment = client.create_mobile_payment(...)
199
+ except AuthenticationError:
200
+ print("Invalid API key")
201
+ except ValidationError as e:
202
+ print(f"Invalid request: {e.message}")
203
+ except NotFoundError:
204
+ print("Payment not found")
205
+ except RateLimitError:
206
+ print("Too many requests, slow down")
207
+ except ServerError:
208
+ print("Snippe server error, try again later")
209
+ ```
210
+
211
+ ## Supported Currencies
212
+
213
+ | Currency | Country |
214
+ |----------|---------|
215
+ | TZS | Tanzania |
216
+ | KES | Kenya |
217
+ | UGX | Uganda |
218
+
219
+ ## License
220
+
221
+ MIT
@@ -0,0 +1,45 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "snippe"
7
+ version = "0.1.0"
8
+ description = "Official Python SDK for Snippe Payment API"
9
+ readme = "README.md"
10
+ license = "MIT"
11
+ requires-python = ">=3.10"
12
+ authors = [
13
+ { name = "Nassdaq", email = "mwaijegakelvin@gmail.com" }
14
+ ]
15
+ keywords = ["Tanzania Payment", "mobile-money", "snippe", "fintech", "africa"]
16
+ classifiers = [
17
+ "Development Status :: 4 - Beta",
18
+ "Intended Audience :: Developers",
19
+ "License :: OSI Approved :: MIT License",
20
+ "Programming Language :: Python :: 3",
21
+ "Programming Language :: Python :: 3.8",
22
+ "Programming Language :: Python :: 3.9",
23
+ "Programming Language :: Python :: 3.10",
24
+ "Programming Language :: Python :: 3.11",
25
+ "Programming Language :: Python :: 3.12",
26
+ "Topic :: Software Development :: Libraries :: Python Modules",
27
+ ]
28
+ dependencies = [
29
+ "httpx>=0.24.0",
30
+ ]
31
+
32
+ [project.optional-dependencies]
33
+ dev = [
34
+ "pytest>=7.0.0",
35
+ "pytest-asyncio>=0.21.0",
36
+ "respx>=0.20.0",
37
+ ]
38
+
39
+ [project.urls]
40
+ Homepage = "https://snippe.sh"
41
+ Documentation = "https://documenter.getpostman.com/view/36488510/2sBXViiWAV#6beb6d54-34a1-4c9c-8a19-acd92a865711"
42
+ Repository = "https://github.com/Neurotech-HQ/snippe-python-sdk"
43
+
44
+ [tool.hatch.build.targets.wheel]
45
+ packages = ["snippe"]
@@ -0,0 +1,67 @@
1
+ """
2
+ Snippe - Python SDK for Snippe Payment API.
3
+
4
+ Accept payments via mobile money, card, and QR code.
5
+
6
+ Usage:
7
+ >>> from snippe import Snippe, Customer
8
+ >>> client = Snippe("your_api_key")
9
+ >>> payment = client.create_mobile_payment(
10
+ ... amount=1000,
11
+ ... currency="TZS",
12
+ ... phone_number="0788500000",
13
+ ... customer=Customer(firstname="John", lastname="Doe")
14
+ ... )
15
+ >>> print(payment.reference)
16
+ """
17
+
18
+ from .client import AsyncSnippe, Snippe
19
+ from .exceptions import (
20
+ AuthenticationError,
21
+ NotFoundError,
22
+ RateLimitError,
23
+ ServerError,
24
+ SnippeError,
25
+ ValidationError,
26
+ WebhookVerificationError,
27
+ )
28
+ from .models import (
29
+ Balance,
30
+ Customer,
31
+ Payment,
32
+ PaymentDetails,
33
+ PaymentList,
34
+ WebhookPayload,
35
+ )
36
+ from .types import Currency, PaymentStatus, PaymentType, WebhookEvent
37
+ from .webhooks import WebhookHandler, verify_webhook
38
+
39
+ __version__ = "0.1.0"
40
+ __all__ = [
41
+ # Clients
42
+ "Snippe",
43
+ "AsyncSnippe",
44
+ # Models
45
+ "Customer",
46
+ "Payment",
47
+ "PaymentDetails",
48
+ "PaymentList",
49
+ "Balance",
50
+ "WebhookPayload",
51
+ # Types
52
+ "PaymentType",
53
+ "PaymentStatus",
54
+ "Currency",
55
+ "WebhookEvent",
56
+ # Webhooks
57
+ "WebhookHandler",
58
+ "verify_webhook",
59
+ # Exceptions
60
+ "SnippeError",
61
+ "AuthenticationError",
62
+ "ValidationError",
63
+ "NotFoundError",
64
+ "RateLimitError",
65
+ "ServerError",
66
+ "WebhookVerificationError",
67
+ ]