raqm-core 0.1.0__py3-none-any.whl
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.
- raqm_core/__init__.py +0 -0
- raqm_core/easypaisa.py +77 -0
- raqm_core/headers/__init__.py +0 -0
- raqm_core/headers/easypaisa.py +7 -0
- raqm_core/headers/jazzcash.py +10 -0
- raqm_core/schemas/__init__.py +0 -0
- raqm_core/schemas/easypaisa.py +66 -0
- raqm_core-0.1.0.dist-info/METADATA +335 -0
- raqm_core-0.1.0.dist-info/RECORD +11 -0
- raqm_core-0.1.0.dist-info/WHEEL +5 -0
- raqm_core-0.1.0.dist-info/top_level.txt +1 -0
raqm_core/__init__.py
ADDED
|
File without changes
|
raqm_core/easypaisa.py
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import httpx
|
|
2
|
+
|
|
3
|
+
from .headers.easypaisa import generate_auth_header
|
|
4
|
+
from .schemas.easypaisa import (
|
|
5
|
+
EasyPaisaInquireTransactionResponse,
|
|
6
|
+
EasyPaisaMAResponse,
|
|
7
|
+
EasyPaisaOTCResponse,
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class EasyPaisa:
|
|
12
|
+
def __init__(
|
|
13
|
+
self,
|
|
14
|
+
store_id: str,
|
|
15
|
+
username: str,
|
|
16
|
+
password: str,
|
|
17
|
+
sandbox: bool,
|
|
18
|
+
client: httpx.AsyncClient | None = None,
|
|
19
|
+
):
|
|
20
|
+
self.store_id = store_id
|
|
21
|
+
self.username = username
|
|
22
|
+
self.password = password
|
|
23
|
+
self.sandbox = sandbox
|
|
24
|
+
self._client = client or httpx.AsyncClient()
|
|
25
|
+
|
|
26
|
+
self.base_url = (
|
|
27
|
+
"https://easypaystg.easypaisa.com.pk/easypay-service/rest/v4/"
|
|
28
|
+
if self.sandbox
|
|
29
|
+
else "https://easypay.easypaisa.com.pk/easypay-service/rest/v4/"
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
async def _post(self, endpoint: str, payload: dict) -> dict:
|
|
33
|
+
header = generate_auth_header(self.username, self.password)
|
|
34
|
+
response = await self._client.post(
|
|
35
|
+
self.base_url + endpoint,
|
|
36
|
+
json=payload,
|
|
37
|
+
headers={"Authorization": header},
|
|
38
|
+
)
|
|
39
|
+
return response.json()
|
|
40
|
+
|
|
41
|
+
async def pay_via_otc(
|
|
42
|
+
self, order_id: str, amount: str, email: str, msisdn: str, token_expiry: str
|
|
43
|
+
):
|
|
44
|
+
request_payload = {
|
|
45
|
+
"orderId": order_id,
|
|
46
|
+
"storeId": self.store_id,
|
|
47
|
+
"transactionAmount": amount,
|
|
48
|
+
"transactionType": "OTC",
|
|
49
|
+
"msisdn": msisdn,
|
|
50
|
+
"emailAddress": email,
|
|
51
|
+
"tokenExpiry": token_expiry,
|
|
52
|
+
}
|
|
53
|
+
data = await self._post("initiate-otc-transaction", request_payload)
|
|
54
|
+
return EasyPaisaOTCResponse(**data)
|
|
55
|
+
|
|
56
|
+
async def pay_via_ma(
|
|
57
|
+
self, order_id: str, amount: str, email: str, mobile_number: str
|
|
58
|
+
):
|
|
59
|
+
request_payload = {
|
|
60
|
+
"orderId": order_id,
|
|
61
|
+
"storeId": self.store_id,
|
|
62
|
+
"transactionAmount": amount,
|
|
63
|
+
"transactionType": "MA",
|
|
64
|
+
"mobileAccountNo": mobile_number,
|
|
65
|
+
"emailAddress": email,
|
|
66
|
+
}
|
|
67
|
+
data = await self._post("initiate-ma-transaction", request_payload)
|
|
68
|
+
return EasyPaisaMAResponse(**data)
|
|
69
|
+
|
|
70
|
+
async def inquire_transaction_status(self, order_id: str, account_number: str):
|
|
71
|
+
request_payload = {
|
|
72
|
+
"orderId": order_id,
|
|
73
|
+
"storeId": self.store_id,
|
|
74
|
+
"accountNum": account_number,
|
|
75
|
+
}
|
|
76
|
+
data = await self._post("inquire-transaction", request_payload)
|
|
77
|
+
return EasyPaisaInquireTransactionResponse(**data)
|
|
File without changes
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
from hashlib import sha256
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def generate_secure_hash(hash_key: str, params: dict) -> str:
|
|
5
|
+
values = "&".join(param[1] for param in sorted(params.items()))
|
|
6
|
+
my_str = hash_key + "&" + values
|
|
7
|
+
|
|
8
|
+
my_bytes = str.encode(my_str)
|
|
9
|
+
my_sha256 = sha256(my_bytes)
|
|
10
|
+
return my_sha256.hexdigest()
|
|
File without changes
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
from enum import Enum
|
|
2
|
+
from typing import Optional
|
|
3
|
+
|
|
4
|
+
from pydantic import BaseModel, Field
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class EasypaisaResponseCode(str, Enum):
|
|
8
|
+
SUCCESS = "0000"
|
|
9
|
+
SYSTEM_ERROR = "0001"
|
|
10
|
+
REQUIRED_FIELD_MISSING = "0002"
|
|
11
|
+
MERCHANT_ACCOUNT_NOT_ACTIVE = "0005"
|
|
12
|
+
INVALID_STORE_ID = "0006"
|
|
13
|
+
STORE_NOT_ACTIVE = "0007"
|
|
14
|
+
PAYMENT_METHOD_NOT_ENABLED = "0008"
|
|
15
|
+
INVALID_CREDENTIALS = "0010"
|
|
16
|
+
LOW_BALANCE = "0013"
|
|
17
|
+
ACCOUNT_DOES_NOT_EXIST = "0014"
|
|
18
|
+
INVALID_TOKEN_EXPIRY = "0015"
|
|
19
|
+
INVALID_EXPIRY = "0016" # date should be future date
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class EasyPaisaResponse(BaseModel):
|
|
23
|
+
orderId: str = Field(
|
|
24
|
+
..., min_length=1, description="Merchant’s system generated Order ID"
|
|
25
|
+
)
|
|
26
|
+
storeId: int = Field(
|
|
27
|
+
ge=0, description="Store ID generated during merchant registration in Easypaisa"
|
|
28
|
+
)
|
|
29
|
+
transactionDateTime: str = Field(
|
|
30
|
+
..., description="Format = dd/MM/yyyy hh:mm [AM/PM]"
|
|
31
|
+
)
|
|
32
|
+
responseCode: EasypaisaResponseCode = Field(
|
|
33
|
+
...,
|
|
34
|
+
min_length=4,
|
|
35
|
+
max_length=4,
|
|
36
|
+
description="Easypaisa generated response codes",
|
|
37
|
+
)
|
|
38
|
+
responseDesc: str = Field(
|
|
39
|
+
..., min_length=3, description="Easypaisa generated response descriptions"
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class EasyPaisaMAResponse(EasyPaisaResponse):
|
|
44
|
+
transactionId: str = Field(..., description="Transaction ID of Ericsson (EWP ID)")
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
class EasyPaisaOTCResponse(EasyPaisaResponse):
|
|
48
|
+
paymentToken: str = Field(..., min_length=1, description="Token generated by OTC")
|
|
49
|
+
paymentTokenExpiryDateTime: str = Field(
|
|
50
|
+
..., description="Format = dd/MM/yyyy hh:mm [AM/PM]"
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
class EasyPaisaInquireTransactionResponse(EasyPaisaResponse):
|
|
55
|
+
accountNum: str = Field(
|
|
56
|
+
..., min_length=1, description="Merchant’s EWP Account Number"
|
|
57
|
+
)
|
|
58
|
+
storeName: str = Field(..., description="Store Name")
|
|
59
|
+
paymentToken: Optional[str] = Field(None, description="Token generated by OTC")
|
|
60
|
+
transactionStatus: str = Field(..., description="The status of transaction")
|
|
61
|
+
transactionAmount: str = Field(..., description="Total transaction amount ")
|
|
62
|
+
paymentTokenExpiryDateTime: Optional[str] = Field(
|
|
63
|
+
None, description="[Only For OTC] Format = dd/MM/yyyy hh:mm [AM/PM]"
|
|
64
|
+
)
|
|
65
|
+
msisdn: str = Field(..., description="Customer MSISDN")
|
|
66
|
+
paymentMode: str = Field(..., description="Type of transaction: OTC, MA, CC")
|
|
@@ -0,0 +1,335 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: raqm-core
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Unified Python SDK for Pakistani payment gateways (EasyPaisa, JazzCash, HBL, ABL, UBL, etc.)
|
|
5
|
+
Requires-Python: >=3.12
|
|
6
|
+
Description-Content-Type: text/markdown
|
|
7
|
+
Requires-Dist: httpx>=0.28.1
|
|
8
|
+
Requires-Dist: pydantic>=2.0
|
|
9
|
+
|
|
10
|
+
# raqm-core
|
|
11
|
+
|
|
12
|
+
**Unified Python SDK for Pakistani payment gateways.**
|
|
13
|
+
|
|
14
|
+
One async, type-safe interface across multiple processors — EasyPaisa, JazzCash, HBL, ABL, UBL, and more.
|
|
15
|
+
|
|
16
|
+
> ⚠️ **Work in progress.** Currently only EasyPaisa is fully implemented. Contributions welcome!
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## Supported Gateways
|
|
21
|
+
|
|
22
|
+
| Gateway | Status |
|
|
23
|
+
|---------|--------|
|
|
24
|
+
| [EasyPaisa](https://easypaisa.com.pk) | ✅ Live |
|
|
25
|
+
| [JazzCash](https://jazzcash.com.pk) | 🚧 Header utils ready |
|
|
26
|
+
| HBL | 📅 Planned |
|
|
27
|
+
| ABL | 📅 Planned |
|
|
28
|
+
| UBL | 📅 Planned |
|
|
29
|
+
| … | 📅 Your gateway here |
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## Features
|
|
34
|
+
|
|
35
|
+
- **Async-first** — built on `httpx.AsyncClient` for non-blocking I/O
|
|
36
|
+
- **Type-safe** — all responses are validated through Pydantic models
|
|
37
|
+
- **Consistent API** — same patterns across all gateways
|
|
38
|
+
- **Mock-friendly** — inject your own `httpx.AsyncClient` for testing
|
|
39
|
+
- **Minimal dependencies** — just `httpx` and `pydantic`
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## Installation
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
pip install raqm-core
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Or with `uv`:
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
uv add raqm-core
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
> Requires Python 3.12+.
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
## Quick Start
|
|
60
|
+
|
|
61
|
+
```python
|
|
62
|
+
import asyncio
|
|
63
|
+
from raqm_core import EasyPaisa
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
async def main():
|
|
67
|
+
ep = EasyPaisa(
|
|
68
|
+
store_id="43",
|
|
69
|
+
username="your_username",
|
|
70
|
+
password="your_password",
|
|
71
|
+
sandbox=True,
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
result = await ep.pay_via_ma(
|
|
75
|
+
order_id="order_123",
|
|
76
|
+
amount="1000.00",
|
|
77
|
+
email="customer@example.com",
|
|
78
|
+
mobile_number="03451234567",
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
print(f"Status: {result.responseCode} — {result.responseDesc}")
|
|
82
|
+
print(f"Transaction ID: {result.transactionId}")
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
asyncio.run(main())
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
---
|
|
89
|
+
|
|
90
|
+
## Usage
|
|
91
|
+
|
|
92
|
+
### EasyPaisa
|
|
93
|
+
|
|
94
|
+
#### Initialisation
|
|
95
|
+
|
|
96
|
+
```python
|
|
97
|
+
from raqm_core import EasyPaisa
|
|
98
|
+
|
|
99
|
+
ep = EasyPaisa(
|
|
100
|
+
store_id="43",
|
|
101
|
+
username="your_username",
|
|
102
|
+
password="your_password",
|
|
103
|
+
sandbox=True, # set False for production
|
|
104
|
+
)
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
You can optionally inject your own `httpx.AsyncClient` — useful for testing with `httpx.MockTransport`:
|
|
108
|
+
|
|
109
|
+
```python
|
|
110
|
+
import httpx
|
|
111
|
+
|
|
112
|
+
client = httpx.AsyncClient(...)
|
|
113
|
+
ep = EasyPaisa(store_id="43", username="...", password="...", sandbox=True, client=client)
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
#### Mobile Account (MA) Payment
|
|
117
|
+
|
|
118
|
+
```python
|
|
119
|
+
result = await ep.pay_via_ma(
|
|
120
|
+
order_id="order_123",
|
|
121
|
+
amount="500.00",
|
|
122
|
+
email="customer@example.com",
|
|
123
|
+
mobile_number="03451234567",
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
# EasyPaisaMAResponse fields:
|
|
127
|
+
result.orderId # str
|
|
128
|
+
result.storeId # int
|
|
129
|
+
result.transactionId # str
|
|
130
|
+
result.transactionDateTime # str (dd/MM/yyyy hh:mm AM/PM)
|
|
131
|
+
result.responseCode # EasypaisaResponseCode (enum)
|
|
132
|
+
result.responseDesc # str
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
#### Over-the-Counter (OTC) Payment
|
|
136
|
+
|
|
137
|
+
```python
|
|
138
|
+
result = await ep.pay_via_otc(
|
|
139
|
+
order_id="order_456",
|
|
140
|
+
amount="1500.00",
|
|
141
|
+
email="customer@example.com",
|
|
142
|
+
msisdn="03451234567",
|
|
143
|
+
token_expiry="01/01/2025 11:59 PM",
|
|
144
|
+
)
|
|
145
|
+
|
|
146
|
+
# EasyPaisaOTCResponse fields (extends base):
|
|
147
|
+
result.paymentToken # str
|
|
148
|
+
result.paymentTokenExpiryDateTime # str
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
#### Transaction Inquiry
|
|
152
|
+
|
|
153
|
+
```python
|
|
154
|
+
result = await ep.inquire_transaction_status(
|
|
155
|
+
order_id="order_123",
|
|
156
|
+
account_number="123456789",
|
|
157
|
+
)
|
|
158
|
+
|
|
159
|
+
# EasyPaisaInquireTransactionResponse fields:
|
|
160
|
+
result.transactionStatus # str (e.g. "COMPLETED")
|
|
161
|
+
result.transactionAmount # str
|
|
162
|
+
result.accountNum # str
|
|
163
|
+
result.storeName # str
|
|
164
|
+
result.msisdn # str
|
|
165
|
+
result.paymentMode # str ("MA", "OTC", "CC")
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
---
|
|
169
|
+
|
|
170
|
+
## Architecture
|
|
171
|
+
|
|
172
|
+
Each payment gateway follows a consistent 3-layer structure:
|
|
173
|
+
|
|
174
|
+
```
|
|
175
|
+
src/
|
|
176
|
+
├── <gateway>.py # Client class — public API
|
|
177
|
+
├── headers/
|
|
178
|
+
│ └── <gateway>.py # Auth / signing helpers
|
|
179
|
+
└── schemas/
|
|
180
|
+
└── <gateway>.py # Pydantic request/response models
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
Current structure:
|
|
184
|
+
|
|
185
|
+
```
|
|
186
|
+
src/
|
|
187
|
+
├── easypaisa.py # EasyPaisa client
|
|
188
|
+
├── headers/
|
|
189
|
+
│ ├── easypaisa.py # Basic Auth header
|
|
190
|
+
│ └── jazzcash.py # SHA-256 secure hash
|
|
191
|
+
└── schemas/
|
|
192
|
+
└── easypaisa.py # EasyPaisa Pydantic models
|
|
193
|
+
|
|
194
|
+
tests/
|
|
195
|
+
├── test_easypaisa.py # EasyPaisa integration tests
|
|
196
|
+
└── headers/
|
|
197
|
+
├── test_easypaisa.py # Auth header unit tests
|
|
198
|
+
└── test_jazzcash.py # Secure hash unit tests
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
---
|
|
202
|
+
|
|
203
|
+
## Adding a New Gateway
|
|
204
|
+
|
|
205
|
+
Want to add support for a new processor? Follow this checklist.
|
|
206
|
+
|
|
207
|
+
### 1. Research the API
|
|
208
|
+
|
|
209
|
+
Understand the gateway's:
|
|
210
|
+
- Authentication mechanism (Basic Auth, HMAC, API key, etc.)
|
|
211
|
+
- Endpoints and request/response formats
|
|
212
|
+
- Error/response codes
|
|
213
|
+
|
|
214
|
+
### 2. Create header helpers
|
|
215
|
+
|
|
216
|
+
`src/headers/<gateway>.py` — authentication or signing logic.
|
|
217
|
+
|
|
218
|
+
```python
|
|
219
|
+
# src/headers/hbl.py
|
|
220
|
+
def generate_signature(api_key: str, payload: dict) -> str:
|
|
221
|
+
...
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
Write unit tests in `tests/headers/test_<gateway>.py`.
|
|
225
|
+
|
|
226
|
+
### 3. Create Pydantic schemas
|
|
227
|
+
|
|
228
|
+
`src/schemas/<gateway>.py` — response models and enums.
|
|
229
|
+
|
|
230
|
+
```python
|
|
231
|
+
# src/schemas/hbl.py
|
|
232
|
+
from pydantic import BaseModel, Field
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
class HBLResponse(BaseModel):
|
|
236
|
+
orderId: str = Field(...)
|
|
237
|
+
responseCode: str = Field(...)
|
|
238
|
+
responseDesc: str = Field(...)
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
### 4. Create the client class
|
|
242
|
+
|
|
243
|
+
`src/<gateway>.py` — async client with a `_post()` helper and public methods.
|
|
244
|
+
|
|
245
|
+
```python
|
|
246
|
+
# src/hbl.py
|
|
247
|
+
import httpx
|
|
248
|
+
from .headers.hbl import generate_signature
|
|
249
|
+
from .schemas.hbl import HBLResponse
|
|
250
|
+
|
|
251
|
+
|
|
252
|
+
class HBL:
|
|
253
|
+
def __init__(self, api_key: str, sandbox: bool, client: httpx.AsyncClient | None = None):
|
|
254
|
+
self._client = client or httpx.AsyncClient()
|
|
255
|
+
...
|
|
256
|
+
|
|
257
|
+
async def _post(self, endpoint: str, payload: dict) -> dict:
|
|
258
|
+
...
|
|
259
|
+
|
|
260
|
+
async def pay(self, order_id: str, amount: str, ...) -> HBLResponse:
|
|
261
|
+
...
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
### 5. Write integration tests
|
|
265
|
+
|
|
266
|
+
`tests/test_<gateway>.py` — use `httpx.MockTransport` to mock responses.
|
|
267
|
+
|
|
268
|
+
```python
|
|
269
|
+
# tests/test_hbl.py
|
|
270
|
+
import httpx
|
|
271
|
+
import pytest
|
|
272
|
+
from raqm_core import HBL
|
|
273
|
+
|
|
274
|
+
|
|
275
|
+
@pytest.mark.asyncio
|
|
276
|
+
async def test_pay_success():
|
|
277
|
+
def handler(request: httpx.Request) -> httpx.Response:
|
|
278
|
+
return httpx.Response(status_code=200, json={...})
|
|
279
|
+
|
|
280
|
+
client = httpx.AsyncClient(transport=httpx.MockTransport(handler))
|
|
281
|
+
hbl = HBL(api_key="test", sandbox=True, client=client)
|
|
282
|
+
result = await hbl.pay(...)
|
|
283
|
+
assert result.responseCode == "0000"
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
### 6. Update this README
|
|
287
|
+
|
|
288
|
+
Add the new gateway to the **Supported Gateways** table with the appropriate status badge.
|
|
289
|
+
|
|
290
|
+
---
|
|
291
|
+
|
|
292
|
+
## Roadmap
|
|
293
|
+
|
|
294
|
+
- [x] EasyPaisa (MA, OTC, inquiry)
|
|
295
|
+
- [ ] JazzCash client + schemas
|
|
296
|
+
- [ ] HBL payment gateway
|
|
297
|
+
- [ ] ABL payment gateway
|
|
298
|
+
- [ ] UBL payment gateway
|
|
299
|
+
- [ ] Standardised error handling across gateways
|
|
300
|
+
- [ ] Request/response logging middleware
|
|
301
|
+
- [ ] CI/CD + automated testing
|
|
302
|
+
|
|
303
|
+
---
|
|
304
|
+
|
|
305
|
+
## Development
|
|
306
|
+
|
|
307
|
+
```bash
|
|
308
|
+
# Clone the repo
|
|
309
|
+
git clone https://github.com/your-username/raqm-core.git
|
|
310
|
+
cd raqm-core
|
|
311
|
+
|
|
312
|
+
# Create a virtual environment
|
|
313
|
+
uv venv
|
|
314
|
+
source .venv/bin/activate
|
|
315
|
+
|
|
316
|
+
# Install dependencies
|
|
317
|
+
uv sync
|
|
318
|
+
|
|
319
|
+
# Run tests
|
|
320
|
+
pytest
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
---
|
|
324
|
+
|
|
325
|
+
## Contributing
|
|
326
|
+
|
|
327
|
+
Contributions are welcome! See [Adding a New Gateway](#adding-a-new-gateway) for the detailed guide.
|
|
328
|
+
|
|
329
|
+
Please open an issue first to discuss your proposed changes.
|
|
330
|
+
|
|
331
|
+
---
|
|
332
|
+
|
|
333
|
+
## License
|
|
334
|
+
|
|
335
|
+
MIT
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
raqm_core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
+
raqm_core/easypaisa.py,sha256=3qOhp9iJwRqrb8ZV1CJJ-VjKOKSytJb6l5OzUoV_RJk,2518
|
|
3
|
+
raqm_core/headers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
|
+
raqm_core/headers/easypaisa.py,sha256=4DFcfYpkohshhvIhwGTaMtFW5wuSut32Pj6NcWx0_48,238
|
|
5
|
+
raqm_core/headers/jazzcash.py,sha256=2xObdRqXtrAl-s2czZhp1Ce2RRSratZPqYaSUJV71ag,297
|
|
6
|
+
raqm_core/schemas/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
7
|
+
raqm_core/schemas/easypaisa.py,sha256=8bUMiwg-UbIeQJCb1Dau7e8gB7Eb05XFN_g8LwUonBA,2346
|
|
8
|
+
raqm_core-0.1.0.dist-info/METADATA,sha256=VPzt8L3L6lfwQ35gOZf7P--L7PLxLT37ik2S4qWGOCE,7335
|
|
9
|
+
raqm_core-0.1.0.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
|
|
10
|
+
raqm_core-0.1.0.dist-info/top_level.txt,sha256=czlRB0RPtVl23KDFQZk7rtchAIxTZlNnNd5hFiXkDT4,10
|
|
11
|
+
raqm_core-0.1.0.dist-info/RECORD,,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
raqm_core
|