airalo-sdk 1.0.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.
Potentially problematic release.
This version of airalo-sdk might be problematic. Click here for more details.
- airalo/__init__.py +29 -0
- airalo/airalo.py +620 -0
- airalo/config.py +146 -0
- airalo/constants/__init__.py +8 -0
- airalo/constants/api_constants.py +49 -0
- airalo/constants/sdk_constants.py +32 -0
- airalo/exceptions/__init__.py +21 -0
- airalo/exceptions/airalo_exception.py +64 -0
- airalo/helpers/__init__.py +9 -0
- airalo/helpers/cached.py +177 -0
- airalo/helpers/cloud_sim_share_validator.py +89 -0
- airalo/helpers/crypt.py +154 -0
- airalo/helpers/date_helper.py +12 -0
- airalo/helpers/signature.py +119 -0
- airalo/resources/__init__.py +8 -0
- airalo/resources/http_resource.py +324 -0
- airalo/resources/multi_http_resource.py +312 -0
- airalo/services/__init__.py +17 -0
- airalo/services/compatibility_devices_service.py +34 -0
- airalo/services/exchange_rates_service.py +69 -0
- airalo/services/future_order_service.py +113 -0
- airalo/services/installation_instructions_service.py +63 -0
- airalo/services/oauth_service.py +186 -0
- airalo/services/order_service.py +463 -0
- airalo/services/packages_service.py +354 -0
- airalo/services/sim_service.py +349 -0
- airalo/services/topup_service.py +127 -0
- airalo/services/voucher_service.py +138 -0
- airalo_sdk-1.0.0.dist-info/METADATA +939 -0
- airalo_sdk-1.0.0.dist-info/RECORD +33 -0
- airalo_sdk-1.0.0.dist-info/WHEEL +5 -0
- airalo_sdk-1.0.0.dist-info/licenses/LICENSE +21 -0
- airalo_sdk-1.0.0.dist-info/top_level.txt +1 -0
airalo/__init__.py
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Airalo Python SDK
|
|
3
|
+
|
|
4
|
+
A Python SDK for integrating with Airalo's Partner API.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from .config import Config
|
|
8
|
+
from .airalo import Airalo
|
|
9
|
+
from .exceptions.airalo_exception import (
|
|
10
|
+
AiraloException,
|
|
11
|
+
ConfigurationError,
|
|
12
|
+
AuthenticationError,
|
|
13
|
+
ValidationError,
|
|
14
|
+
APIError,
|
|
15
|
+
NetworkError,
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
__version__ = "1.0.0"
|
|
19
|
+
|
|
20
|
+
__all__ = [
|
|
21
|
+
"Airalo",
|
|
22
|
+
"Config",
|
|
23
|
+
"AiraloException",
|
|
24
|
+
"ConfigurationError",
|
|
25
|
+
"AuthenticationError",
|
|
26
|
+
"ValidationError",
|
|
27
|
+
"APIError",
|
|
28
|
+
"NetworkError",
|
|
29
|
+
]
|
airalo/airalo.py
ADDED
|
@@ -0,0 +1,620 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Airalo Main Client Module
|
|
3
|
+
|
|
4
|
+
This module provides the main Airalo client class for SDK operations.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from typing import Any, Dict, List, Optional, Union
|
|
8
|
+
|
|
9
|
+
from .config import Config
|
|
10
|
+
from .helpers.signature import Signature
|
|
11
|
+
from .services.sim_service import SimService
|
|
12
|
+
from .services.oauth_service import OAuthService
|
|
13
|
+
from .services.order_service import OrderService
|
|
14
|
+
from .services.topup_service import TopupService
|
|
15
|
+
from .resources.http_resource import HttpResource
|
|
16
|
+
from .services.packages_service import PackagesService
|
|
17
|
+
from .exceptions.airalo_exception import AiraloException
|
|
18
|
+
from .resources.multi_http_resource import MultiHttpResource
|
|
19
|
+
from .services.future_order_service import FutureOrderService
|
|
20
|
+
from .services.compatibility_devices_service import CompatibilityDevicesService
|
|
21
|
+
from .services.installation_instructions_service import InstallationInstructionsService
|
|
22
|
+
from .services.exchange_rates_service import ExchangeRatesService
|
|
23
|
+
from .services.voucher_service import VoucherService
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class Airalo:
|
|
27
|
+
"""
|
|
28
|
+
Main Airalo SDK client.
|
|
29
|
+
|
|
30
|
+
Provides access to all Airalo API operations through a single interface.
|
|
31
|
+
"""
|
|
32
|
+
|
|
33
|
+
# Class-level pool for resource sharing
|
|
34
|
+
_pool: Dict[str, Any] = {}
|
|
35
|
+
|
|
36
|
+
def __init__(self, config: Union[Dict[str, Any], Config, str]):
|
|
37
|
+
"""
|
|
38
|
+
Initialize Airalo client.
|
|
39
|
+
|
|
40
|
+
Args:
|
|
41
|
+
config: Configuration data (dict, Config object, or JSON string)
|
|
42
|
+
|
|
43
|
+
Raises:
|
|
44
|
+
AiraloException: If initialization fails
|
|
45
|
+
"""
|
|
46
|
+
try:
|
|
47
|
+
self._init_resources(config)
|
|
48
|
+
self._init_services()
|
|
49
|
+
|
|
50
|
+
# Store resources in pool for reuse
|
|
51
|
+
if not self._pool:
|
|
52
|
+
self._pool = {
|
|
53
|
+
"config": self._config,
|
|
54
|
+
"curl": self._http,
|
|
55
|
+
"multi_curl": self._multi_http,
|
|
56
|
+
"signature": self._signature,
|
|
57
|
+
"oauth": self._oauth,
|
|
58
|
+
"installation_instructions": self._installation_instructions,
|
|
59
|
+
"topup": self._topup,
|
|
60
|
+
"future_order": self._future_order,
|
|
61
|
+
"compatibility_devices": self._compatibility_devices,
|
|
62
|
+
"sim": self._sim,
|
|
63
|
+
"exchange_rates": self._exchange_rates,
|
|
64
|
+
"voucher": self._voucher,
|
|
65
|
+
}
|
|
66
|
+
except Exception as e:
|
|
67
|
+
self._pool = {}
|
|
68
|
+
raise AiraloException(f"Airalo SDK initialization failed: {str(e)}")
|
|
69
|
+
|
|
70
|
+
def _init_resources(self, config: Union[Dict[str, Any], Config, str]) -> None:
|
|
71
|
+
"""
|
|
72
|
+
Initialize core resources.
|
|
73
|
+
|
|
74
|
+
Args:
|
|
75
|
+
config: Configuration data
|
|
76
|
+
"""
|
|
77
|
+
# Initialize configuration
|
|
78
|
+
if isinstance(config, Config):
|
|
79
|
+
self._config = config
|
|
80
|
+
else:
|
|
81
|
+
self._config = self._pool.get("config") or Config(config)
|
|
82
|
+
|
|
83
|
+
# Initialize HTTP resources
|
|
84
|
+
self._http = self._pool.get("curl") or HttpResource(self._config)
|
|
85
|
+
self._multi_http = self._pool.get("multi_curl") or MultiHttpResource(
|
|
86
|
+
self._config
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
# Initialize signature helper
|
|
90
|
+
self._signature = self._pool.get("signature") or Signature(
|
|
91
|
+
self._config.get("client_secret")
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
def _init_services(self) -> None:
|
|
95
|
+
"""
|
|
96
|
+
Initialize service classes.
|
|
97
|
+
|
|
98
|
+
Raises:
|
|
99
|
+
AiraloException: If authentication fails
|
|
100
|
+
"""
|
|
101
|
+
# Initialize OAuth service
|
|
102
|
+
self._oauth = self._pool.get("oauth") or OAuthService(
|
|
103
|
+
self._config, self._http, self._signature
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
# Get access token
|
|
107
|
+
self._access_token = self._oauth.get_access_token()
|
|
108
|
+
if not self._access_token:
|
|
109
|
+
raise AiraloException("Failed to obtain access token")
|
|
110
|
+
|
|
111
|
+
# Initialize other services
|
|
112
|
+
self._packages = self._pool.get("packages") or PackagesService(
|
|
113
|
+
self._config, self._http, self._access_token
|
|
114
|
+
)
|
|
115
|
+
self._order = self._pool.get("order") or OrderService(
|
|
116
|
+
self._config,
|
|
117
|
+
self._http,
|
|
118
|
+
self._multi_http,
|
|
119
|
+
self._signature,
|
|
120
|
+
self._access_token,
|
|
121
|
+
)
|
|
122
|
+
self._topup = self._pool.get("topup") or TopupService(
|
|
123
|
+
self._config, self._http, self._signature, self._access_token
|
|
124
|
+
)
|
|
125
|
+
self._installation_instructions = self._pool.get(
|
|
126
|
+
"installation_instructions"
|
|
127
|
+
) or InstallationInstructionsService(
|
|
128
|
+
self._config, self._http, self._access_token
|
|
129
|
+
)
|
|
130
|
+
self._future_order = self._pool.get("future_order") or FutureOrderService(
|
|
131
|
+
self._config, self._http, self._signature, self._access_token
|
|
132
|
+
)
|
|
133
|
+
self._compatibility_devices = self._pool.get(
|
|
134
|
+
"compatibility_devices"
|
|
135
|
+
) or CompatibilityDevicesService(self._config, self._http, self._access_token)
|
|
136
|
+
self._sim = self._pool.get("sim") or SimService(
|
|
137
|
+
self._config, self._http, self._multi_http, self._access_token
|
|
138
|
+
)
|
|
139
|
+
self._exchange_rates = self._pool.get("exchange_rates") or ExchangeRatesService(
|
|
140
|
+
self._config, self._http, self._access_token
|
|
141
|
+
)
|
|
142
|
+
self._voucher = self._pool.get("voucher") or VoucherService(
|
|
143
|
+
self._config, self._http, self._signature, self._access_token
|
|
144
|
+
)
|
|
145
|
+
|
|
146
|
+
# =====================================================
|
|
147
|
+
# OAuth Methods
|
|
148
|
+
# =====================================================
|
|
149
|
+
|
|
150
|
+
def get_access_token(self) -> Optional[str]:
|
|
151
|
+
"""
|
|
152
|
+
Get current access token.
|
|
153
|
+
|
|
154
|
+
Returns:
|
|
155
|
+
Access token or None
|
|
156
|
+
"""
|
|
157
|
+
return self._access_token
|
|
158
|
+
|
|
159
|
+
def refresh_token(self) -> Optional[str]:
|
|
160
|
+
"""
|
|
161
|
+
Refresh access token.
|
|
162
|
+
|
|
163
|
+
Returns:
|
|
164
|
+
New access token or None
|
|
165
|
+
"""
|
|
166
|
+
self._access_token = self._oauth.refresh_token()
|
|
167
|
+
return self._access_token
|
|
168
|
+
|
|
169
|
+
# =====================================================
|
|
170
|
+
# Package Methods
|
|
171
|
+
# =====================================================
|
|
172
|
+
|
|
173
|
+
def get_all_packages(
|
|
174
|
+
self,
|
|
175
|
+
flat: bool = False,
|
|
176
|
+
limit: Optional[int] = None,
|
|
177
|
+
page: Optional[int] = None,
|
|
178
|
+
) -> Optional[Dict]:
|
|
179
|
+
"""
|
|
180
|
+
Get all available packages.
|
|
181
|
+
|
|
182
|
+
Args:
|
|
183
|
+
flat: If True, return flattened response
|
|
184
|
+
limit: Number of results per page
|
|
185
|
+
page: Page number
|
|
186
|
+
|
|
187
|
+
Returns:
|
|
188
|
+
Packages data or None
|
|
189
|
+
"""
|
|
190
|
+
return self._packages.get_all_packages(flat, limit, page)
|
|
191
|
+
|
|
192
|
+
def get_sim_packages(
|
|
193
|
+
self,
|
|
194
|
+
flat: bool = False,
|
|
195
|
+
limit: Optional[int] = None,
|
|
196
|
+
page: Optional[int] = None,
|
|
197
|
+
) -> Optional[Dict]:
|
|
198
|
+
"""
|
|
199
|
+
Get SIM-only packages.
|
|
200
|
+
|
|
201
|
+
Args:
|
|
202
|
+
flat: If True, return flattened response
|
|
203
|
+
limit: Number of results per page
|
|
204
|
+
page: Page number
|
|
205
|
+
|
|
206
|
+
Returns:
|
|
207
|
+
Packages data or None
|
|
208
|
+
"""
|
|
209
|
+
return self._packages.get_sim_packages(flat, limit, page)
|
|
210
|
+
|
|
211
|
+
def get_local_packages(
|
|
212
|
+
self,
|
|
213
|
+
flat: bool = False,
|
|
214
|
+
limit: Optional[int] = None,
|
|
215
|
+
page: Optional[int] = None,
|
|
216
|
+
) -> Optional[Dict]:
|
|
217
|
+
"""
|
|
218
|
+
Get local packages.
|
|
219
|
+
|
|
220
|
+
Args:
|
|
221
|
+
flat: If True, return flattened response
|
|
222
|
+
limit: Number of results per page
|
|
223
|
+
page: Page number
|
|
224
|
+
|
|
225
|
+
Returns:
|
|
226
|
+
Packages data or None
|
|
227
|
+
"""
|
|
228
|
+
return self._packages.get_local_packages(flat, limit, page)
|
|
229
|
+
|
|
230
|
+
def get_global_packages(
|
|
231
|
+
self,
|
|
232
|
+
flat: bool = False,
|
|
233
|
+
limit: Optional[int] = None,
|
|
234
|
+
page: Optional[int] = None,
|
|
235
|
+
) -> Optional[Dict]:
|
|
236
|
+
"""
|
|
237
|
+
Get global packages.
|
|
238
|
+
|
|
239
|
+
Args:
|
|
240
|
+
flat: If True, return flattened response
|
|
241
|
+
limit: Number of results per page
|
|
242
|
+
page: Page number
|
|
243
|
+
|
|
244
|
+
Returns:
|
|
245
|
+
Packages data or None
|
|
246
|
+
"""
|
|
247
|
+
return self._packages.get_global_packages(flat, limit, page)
|
|
248
|
+
|
|
249
|
+
def get_country_packages(
|
|
250
|
+
self, country_code: str, flat: bool = False, limit: Optional[int] = None
|
|
251
|
+
) -> Optional[Dict]:
|
|
252
|
+
"""
|
|
253
|
+
Get packages for a specific country.
|
|
254
|
+
|
|
255
|
+
Args:
|
|
256
|
+
country_code: ISO country code
|
|
257
|
+
flat: If True, return flattened response
|
|
258
|
+
limit: Number of results
|
|
259
|
+
|
|
260
|
+
Returns:
|
|
261
|
+
Packages data or None
|
|
262
|
+
"""
|
|
263
|
+
return self._packages.get_country_packages(country_code, flat, limit)
|
|
264
|
+
|
|
265
|
+
# =====================================================
|
|
266
|
+
# Order Methods
|
|
267
|
+
# =====================================================
|
|
268
|
+
|
|
269
|
+
def order(
|
|
270
|
+
self, package_id: str, quantity: int, description: Optional[str] = None
|
|
271
|
+
) -> Optional[Dict]:
|
|
272
|
+
"""
|
|
273
|
+
Create an order.
|
|
274
|
+
|
|
275
|
+
Args:
|
|
276
|
+
package_id: Package ID to order
|
|
277
|
+
quantity: Number of SIMs
|
|
278
|
+
description: Order description
|
|
279
|
+
|
|
280
|
+
Returns:
|
|
281
|
+
Order data or None
|
|
282
|
+
"""
|
|
283
|
+
return self._order.create_order(
|
|
284
|
+
{
|
|
285
|
+
"package_id": package_id,
|
|
286
|
+
"quantity": quantity,
|
|
287
|
+
"type": "sim",
|
|
288
|
+
"description": description or "Order placed via Airalo Python SDK",
|
|
289
|
+
}
|
|
290
|
+
)
|
|
291
|
+
|
|
292
|
+
def order_with_email_sim_share(
|
|
293
|
+
self,
|
|
294
|
+
package_id: str,
|
|
295
|
+
quantity: int,
|
|
296
|
+
esim_cloud: Dict[str, Any],
|
|
297
|
+
description: Optional[str] = None,
|
|
298
|
+
) -> Optional[Dict]:
|
|
299
|
+
"""
|
|
300
|
+
Create an order with email SIM sharing.
|
|
301
|
+
|
|
302
|
+
Args:
|
|
303
|
+
package_id: Package ID to order
|
|
304
|
+
quantity: Number of SIMs
|
|
305
|
+
esim_cloud: Email sharing configuration
|
|
306
|
+
description: Order description
|
|
307
|
+
|
|
308
|
+
Returns:
|
|
309
|
+
Order data or None
|
|
310
|
+
"""
|
|
311
|
+
return self._order.create_order_with_email_sim_share(
|
|
312
|
+
{
|
|
313
|
+
"package_id": package_id,
|
|
314
|
+
"quantity": quantity,
|
|
315
|
+
"type": "sim",
|
|
316
|
+
"description": description or "Order placed via Airalo Python SDK",
|
|
317
|
+
},
|
|
318
|
+
esim_cloud,
|
|
319
|
+
)
|
|
320
|
+
|
|
321
|
+
def order_async(
|
|
322
|
+
self,
|
|
323
|
+
package_id: str,
|
|
324
|
+
quantity: int,
|
|
325
|
+
webhook_url: Optional[str] = None,
|
|
326
|
+
description: Optional[str] = None,
|
|
327
|
+
) -> Optional[Dict]:
|
|
328
|
+
"""
|
|
329
|
+
Create an asynchronous order.
|
|
330
|
+
|
|
331
|
+
Args:
|
|
332
|
+
package_id: Package ID to order
|
|
333
|
+
quantity: Number of SIMs
|
|
334
|
+
webhook_url: Webhook URL for notifications
|
|
335
|
+
description: Order description
|
|
336
|
+
|
|
337
|
+
Returns:
|
|
338
|
+
Order data or None
|
|
339
|
+
"""
|
|
340
|
+
return self._order.create_order_async(
|
|
341
|
+
{
|
|
342
|
+
"package_id": package_id,
|
|
343
|
+
"quantity": quantity,
|
|
344
|
+
"type": "sim",
|
|
345
|
+
"webhook_url": webhook_url,
|
|
346
|
+
"description": description or "Order placed via Airalo Python SDK",
|
|
347
|
+
}
|
|
348
|
+
)
|
|
349
|
+
|
|
350
|
+
def order_bulk(
|
|
351
|
+
self,
|
|
352
|
+
packages: Union[Dict[str, int], List[Dict]],
|
|
353
|
+
description: Optional[str] = None,
|
|
354
|
+
) -> Optional[Dict]:
|
|
355
|
+
"""
|
|
356
|
+
Create bulk orders.
|
|
357
|
+
|
|
358
|
+
Args:
|
|
359
|
+
packages: Either dict of package_id: quantity or list of dicts
|
|
360
|
+
description: Order description
|
|
361
|
+
|
|
362
|
+
Returns:
|
|
363
|
+
Order data or None
|
|
364
|
+
"""
|
|
365
|
+
if not packages:
|
|
366
|
+
return None
|
|
367
|
+
return self._order.create_order_bulk(packages, description)
|
|
368
|
+
|
|
369
|
+
def order_bulk_with_email_sim_share(
|
|
370
|
+
self,
|
|
371
|
+
packages: Union[Dict[str, int], List[Dict]],
|
|
372
|
+
esim_cloud: Dict[str, Any],
|
|
373
|
+
description: Optional[str] = None,
|
|
374
|
+
) -> Optional[Dict]:
|
|
375
|
+
"""
|
|
376
|
+
Create bulk orders with email SIM sharing.
|
|
377
|
+
|
|
378
|
+
Args:
|
|
379
|
+
packages: Package IDs and quantities
|
|
380
|
+
esim_cloud: Email sharing configuration
|
|
381
|
+
description: Order description
|
|
382
|
+
|
|
383
|
+
Returns:
|
|
384
|
+
Order data or None
|
|
385
|
+
"""
|
|
386
|
+
if not packages:
|
|
387
|
+
return None
|
|
388
|
+
return self._order.create_order_bulk_with_email_sim_share(
|
|
389
|
+
packages, esim_cloud, description
|
|
390
|
+
)
|
|
391
|
+
|
|
392
|
+
def order_async_bulk(
|
|
393
|
+
self,
|
|
394
|
+
packages: Union[Dict[str, int], List[Dict]],
|
|
395
|
+
webhook_url: Optional[str] = None,
|
|
396
|
+
description: Optional[str] = None,
|
|
397
|
+
) -> Optional[Dict]:
|
|
398
|
+
"""
|
|
399
|
+
Create bulk asynchronous orders.
|
|
400
|
+
|
|
401
|
+
Args:
|
|
402
|
+
packages: Package IDs and quantities
|
|
403
|
+
webhook_url: Webhook URL for notifications
|
|
404
|
+
description: Order description
|
|
405
|
+
|
|
406
|
+
Returns:
|
|
407
|
+
Order data or None
|
|
408
|
+
"""
|
|
409
|
+
if not packages:
|
|
410
|
+
return None
|
|
411
|
+
return self._order.create_order_async_bulk(packages, webhook_url, description)
|
|
412
|
+
|
|
413
|
+
def topup(
|
|
414
|
+
self, package_id: str, iccid: str, description: Optional[str] = None
|
|
415
|
+
) -> Optional[Dict]:
|
|
416
|
+
"""
|
|
417
|
+
Create a top-up.
|
|
418
|
+
|
|
419
|
+
Args:
|
|
420
|
+
package_id: Package ID to top-up
|
|
421
|
+
iccid: ICCID of the SIM to top-up
|
|
422
|
+
description: Optional description for the top-up
|
|
423
|
+
Returns:
|
|
424
|
+
Top-up data or None
|
|
425
|
+
"""
|
|
426
|
+
return self._topup.create_topup(
|
|
427
|
+
{
|
|
428
|
+
"package_id": package_id,
|
|
429
|
+
"iccid": iccid,
|
|
430
|
+
"description": description or "Topup placed via Airalo Python SDK",
|
|
431
|
+
}
|
|
432
|
+
)
|
|
433
|
+
|
|
434
|
+
# =====================================================
|
|
435
|
+
# Utility Methods
|
|
436
|
+
# =====================================================
|
|
437
|
+
|
|
438
|
+
def get_config(self) -> Config:
|
|
439
|
+
"""
|
|
440
|
+
Get current configuration.
|
|
441
|
+
|
|
442
|
+
Returns:
|
|
443
|
+
Configuration object
|
|
444
|
+
"""
|
|
445
|
+
return self._config
|
|
446
|
+
|
|
447
|
+
def get_environment(self) -> str:
|
|
448
|
+
"""
|
|
449
|
+
Get current environment.
|
|
450
|
+
|
|
451
|
+
Returns:
|
|
452
|
+
Environment name ('sandbox' or 'production')
|
|
453
|
+
"""
|
|
454
|
+
return self._config.get_environment()
|
|
455
|
+
|
|
456
|
+
def clear_cache(self) -> None:
|
|
457
|
+
"""Clear all cached data."""
|
|
458
|
+
from .helpers.cached import Cached
|
|
459
|
+
|
|
460
|
+
Cached.clear_cache()
|
|
461
|
+
|
|
462
|
+
def __repr__(self) -> str:
|
|
463
|
+
"""String representation of Airalo client."""
|
|
464
|
+
return f"<Airalo(env='{self.get_environment()}')>"
|
|
465
|
+
|
|
466
|
+
# =====================================================
|
|
467
|
+
# Installation Instruction Methods
|
|
468
|
+
# =====================================================
|
|
469
|
+
|
|
470
|
+
def get_installation_instructions(
|
|
471
|
+
self, params: Optional[Dict[str, Any]] = None
|
|
472
|
+
) -> Optional[Any]:
|
|
473
|
+
"""
|
|
474
|
+
Get installation instructions for a given ICCID and language.
|
|
475
|
+
|
|
476
|
+
Args:
|
|
477
|
+
params: Dictionary with at least 'iccid' key, optionally 'language'.
|
|
478
|
+
|
|
479
|
+
Returns:
|
|
480
|
+
Response data as dictionary or None
|
|
481
|
+
"""
|
|
482
|
+
return self._installation_instructions.get_instructions(params or {})
|
|
483
|
+
|
|
484
|
+
# =====================================================
|
|
485
|
+
# Future Order Methods
|
|
486
|
+
# =====================================================
|
|
487
|
+
|
|
488
|
+
def create_future_order(self, payload: Dict[str, Any]) -> Optional[Dict]:
|
|
489
|
+
"""
|
|
490
|
+
Create a future order.
|
|
491
|
+
|
|
492
|
+
Args:
|
|
493
|
+
payload: Dictionary containing order details.
|
|
494
|
+
|
|
495
|
+
Returns:
|
|
496
|
+
Response data as dictionary or None.
|
|
497
|
+
"""
|
|
498
|
+
return self._future_order.create_future_order(payload)
|
|
499
|
+
|
|
500
|
+
def cancel_future_order(self, payload: Dict[str, Any]) -> Optional[Dict]:
|
|
501
|
+
"""
|
|
502
|
+
Cancel a future order.
|
|
503
|
+
|
|
504
|
+
Args:
|
|
505
|
+
payload: Dictionary containing cancellation details.
|
|
506
|
+
|
|
507
|
+
Returns:
|
|
508
|
+
Response data as dictionary or None.
|
|
509
|
+
"""
|
|
510
|
+
return self._future_order.cancel_future_order(payload)
|
|
511
|
+
|
|
512
|
+
# =====================================================
|
|
513
|
+
# Compatible devices Methods
|
|
514
|
+
# =====================================================
|
|
515
|
+
|
|
516
|
+
def get_compatible_devices(self) -> Optional[Any]:
|
|
517
|
+
"""
|
|
518
|
+
Fetch compatible devices from Airalo API.
|
|
519
|
+
|
|
520
|
+
Returns:
|
|
521
|
+
Response data as dictionary or None
|
|
522
|
+
"""
|
|
523
|
+
return self._compatibility_devices.get_compatible_devices()
|
|
524
|
+
|
|
525
|
+
# =====================================================
|
|
526
|
+
# SIM Methods
|
|
527
|
+
# =====================================================
|
|
528
|
+
|
|
529
|
+
def sim_usage(self, iccid: str) -> Optional[Dict]:
|
|
530
|
+
"""
|
|
531
|
+
Get SIM usage information.
|
|
532
|
+
|
|
533
|
+
Args:
|
|
534
|
+
iccid: ICCID of the SIM
|
|
535
|
+
|
|
536
|
+
Returns:
|
|
537
|
+
SIM usage data or None
|
|
538
|
+
"""
|
|
539
|
+
return self._sim.get_usage(iccid)
|
|
540
|
+
|
|
541
|
+
def sim_usage_bulk(self, iccids: List[str]) -> Optional[Dict]:
|
|
542
|
+
"""
|
|
543
|
+
Get usage information for multiple SIMs.
|
|
544
|
+
|
|
545
|
+
Args:
|
|
546
|
+
iccids: List of ICCIDs
|
|
547
|
+
|
|
548
|
+
Returns:
|
|
549
|
+
Dict mapping ICCIDs to usage data
|
|
550
|
+
"""
|
|
551
|
+
return self._sim.get_usage_bulk(iccids)
|
|
552
|
+
|
|
553
|
+
def get_sim_topups(self, iccid: str) -> Optional[Dict]:
|
|
554
|
+
"""
|
|
555
|
+
Get SIM topup history.
|
|
556
|
+
|
|
557
|
+
Args:
|
|
558
|
+
iccid: ICCID of the SIM
|
|
559
|
+
|
|
560
|
+
Returns:
|
|
561
|
+
Topup history or None
|
|
562
|
+
"""
|
|
563
|
+
return self._sim.get_topups(iccid)
|
|
564
|
+
|
|
565
|
+
def get_sim_package_history(self, iccid: str) -> Optional[Dict]:
|
|
566
|
+
"""
|
|
567
|
+
Get SIM package history.
|
|
568
|
+
|
|
569
|
+
Args:
|
|
570
|
+
iccid: ICCID of the SIM
|
|
571
|
+
|
|
572
|
+
Returns:
|
|
573
|
+
Package history or None
|
|
574
|
+
"""
|
|
575
|
+
return self._sim.get_package_history(iccid)
|
|
576
|
+
|
|
577
|
+
# =====================================================
|
|
578
|
+
# Exchange Rates Methods
|
|
579
|
+
# =====================================================
|
|
580
|
+
|
|
581
|
+
def get_exchange_rates(
|
|
582
|
+
self, params: Optional[Dict[str, str]] = None
|
|
583
|
+
) -> Optional[Dict]:
|
|
584
|
+
"""
|
|
585
|
+
Get exchange rates for given parameters.
|
|
586
|
+
|
|
587
|
+
Args:
|
|
588
|
+
params: Optional dict with keys like 'date' and 'to'
|
|
589
|
+
|
|
590
|
+
Returns:
|
|
591
|
+
Exchange rate data or None
|
|
592
|
+
"""
|
|
593
|
+
return self._exchange_rates.exchange_rates(params or {})
|
|
594
|
+
|
|
595
|
+
# Voucher Methods
|
|
596
|
+
# =====================================================
|
|
597
|
+
|
|
598
|
+
def create_voucher(self, payload: Dict[str, Any]) -> Optional[Dict]:
|
|
599
|
+
"""
|
|
600
|
+
Create a regular voucher.
|
|
601
|
+
|
|
602
|
+
Args:
|
|
603
|
+
payload: Dictionary with voucher parameters
|
|
604
|
+
|
|
605
|
+
Returns:
|
|
606
|
+
Response data or None
|
|
607
|
+
"""
|
|
608
|
+
return self._voucher.create_voucher(payload)
|
|
609
|
+
|
|
610
|
+
def create_esim_voucher(self, payload: Dict[str, Any]) -> Optional[Dict]:
|
|
611
|
+
"""
|
|
612
|
+
Create an eSIM voucher.
|
|
613
|
+
|
|
614
|
+
Args:
|
|
615
|
+
payload: Dictionary with eSIM voucher parameters
|
|
616
|
+
|
|
617
|
+
Returns:
|
|
618
|
+
Response data or None
|
|
619
|
+
"""
|
|
620
|
+
return self._voucher.create_esim_voucher(payload)
|