Skip to content

Commit 29aebc0

Browse files
authored
Merge pull request #29 from RafaelJohn9/feat/BillManager
Feat/bill manager
2 parents 4c192f8 + c8c733a commit 29aebc0

5 files changed

Lines changed: 1033 additions & 0 deletions

File tree

mpesa_sdk/bill_manager/__init__.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
from .schemas import (
2+
BillManagerOptInRequest,
3+
BillManagerOptInResponse,
4+
BillManagerUpdateOptInRequest,
5+
BillManagerUpdateOptInResponse,
6+
BillManagerSingleInvoiceRequest,
7+
BillManagerSingleInvoiceResponse,
8+
BillManagerBulkInvoiceRequest,
9+
BillManagerBulkInvoiceResponse,
10+
BillManagerCancelSingleInvoiceRequest,
11+
BillManagerCancelBulkInvoiceRequest,
12+
BillManagerCancelInvoiceResponse,
13+
BillManagerPaymentNotificationRequest,
14+
BillManagerPaymentNotificationResponse,
15+
BillManagerPaymentAcknowledgmentRequest,
16+
BillManagerPaymentAcknowledgmentResponse,
17+
)
18+
19+
from .bill_manager import BillManager
20+
21+
__all__ = [
22+
"BillManagerOptInRequest",
23+
"BillManagerOptInResponse",
24+
"BillManagerUpdateOptInRequest",
25+
"BillManagerUpdateOptInResponse",
26+
"BillManagerSingleInvoiceRequest",
27+
"BillManagerSingleInvoiceResponse",
28+
"BillManagerBulkInvoiceRequest",
29+
"BillManagerBulkInvoiceResponse",
30+
"BillManagerCancelSingleInvoiceRequest",
31+
"BillManagerCancelBulkInvoiceRequest",
32+
"BillManagerCancelInvoiceResponse",
33+
"BillManagerPaymentNotificationRequest",
34+
"BillManagerPaymentNotificationResponse",
35+
"BillManagerPaymentAcknowledgmentRequest",
36+
"BillManagerPaymentAcknowledgmentResponse",
37+
"BillManager",
38+
]
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
"""BillManager: Handles M-PESA Bill Manager API interactions.
2+
3+
This module provides functionality for onboarding, invoicing, payment notifications,
4+
acknowledgments, and invoice cancellation using the M-PESA Bill Manager API.
5+
Requires a valid access token for authentication and uses the HttpClient for HTTP requests.
6+
"""
7+
8+
from pydantic import BaseModel, ConfigDict
9+
from typing import Optional
10+
from mpesa_sdk.auth import TokenManager
11+
from mpesa_sdk.http_client import HttpClient
12+
13+
from .schemas import (
14+
BillManagerOptInRequest,
15+
BillManagerOptInResponse,
16+
BillManagerUpdateOptInRequest,
17+
BillManagerUpdateOptInResponse,
18+
BillManagerSingleInvoiceRequest,
19+
BillManagerSingleInvoiceResponse,
20+
BillManagerBulkInvoiceRequest,
21+
BillManagerBulkInvoiceResponse,
22+
BillManagerCancelSingleInvoiceRequest,
23+
BillManagerCancelBulkInvoiceRequest,
24+
BillManagerCancelInvoiceResponse,
25+
)
26+
27+
28+
class BillManager(BaseModel):
29+
"""Represents the Bill Manager API client for M-PESA operations."""
30+
31+
http_client: HttpClient
32+
token_manager: TokenManager
33+
app_key: Optional[str] = None
34+
35+
model_config = ConfigDict(arbitrary_types_allowed=True)
36+
37+
def opt_in(self, request: BillManagerOptInRequest) -> BillManagerOptInResponse:
38+
"""Onboard a paybill to Bill Manager."""
39+
url = "/v1/billmanager-invoice/optin"
40+
headers = {
41+
"Authorization": f"Bearer {self.token_manager.get_token()}",
42+
"Content-Type": "application/json",
43+
}
44+
response_data = self.http_client.post(
45+
url, json=request.model_dump(mode="json"), headers=headers
46+
)
47+
return BillManagerOptInResponse(**response_data)
48+
49+
def _ensure_app_key(self):
50+
if self.app_key is None:
51+
raise ValueError(
52+
"app_key must be set for this operation. You must pass it when initializing BillManager."
53+
)
54+
55+
def update_opt_in(
56+
self, request: BillManagerUpdateOptInRequest
57+
) -> BillManagerUpdateOptInResponse:
58+
"""Update opt-in details for Bill Manager."""
59+
self._ensure_app_key()
60+
url = "/v1/billmanager-invoice/change-optin-details"
61+
headers = {
62+
"Authorization": f"Bearer {self.token_manager.get_token()}",
63+
"Content-Type": "application/json",
64+
"appKey": f"{self.app_key}",
65+
}
66+
response_data = self.http_client.post(
67+
url, json=request.model_dump(mode="json"), headers=headers
68+
)
69+
return BillManagerUpdateOptInResponse(**response_data)
70+
71+
def send_single_invoice(
72+
self, request: BillManagerSingleInvoiceRequest
73+
) -> BillManagerSingleInvoiceResponse:
74+
"""Send a single invoice via Bill Manager."""
75+
self._ensure_app_key()
76+
url = "/v1/billmanager-invoice/single-invoicing"
77+
headers = {
78+
"Authorization": f"Bearer {self.token_manager.get_token()}",
79+
"Content-Type": "application/json",
80+
"appKey": f"{self.app_key}",
81+
}
82+
response_data = self.http_client.post(
83+
url, json=request.model_dump(mode="json"), headers=headers
84+
)
85+
return BillManagerSingleInvoiceResponse(**response_data)
86+
87+
def send_bulk_invoice(
88+
self, request: BillManagerBulkInvoiceRequest
89+
) -> BillManagerBulkInvoiceResponse:
90+
"""Send multiple invoices via Bill Manager."""
91+
self._ensure_app_key()
92+
url = "/v1/billmanager-invoice/bulk-invoicing"
93+
headers = {
94+
"Authorization": f"Bearer {self.token_manager.get_token()}",
95+
"Content-Type": "application/json",
96+
"appKey": f"{self.app_key}",
97+
}
98+
response_data = self.http_client.post(
99+
url, json=request.model_dump(mode="json"), headers=headers
100+
)
101+
return BillManagerBulkInvoiceResponse(**response_data)
102+
103+
def cancel_single_invoice(
104+
self, request: BillManagerCancelSingleInvoiceRequest
105+
) -> BillManagerCancelInvoiceResponse:
106+
"""Cancel a single invoice via Bill Manager."""
107+
self._ensure_app_key()
108+
url = "/v1/billmanager-invoice/cancel-single-invoice"
109+
headers = {
110+
"Authorization": f"Bearer {self.token_manager.get_token()}",
111+
"Content-Type": "application/json",
112+
"appKey": f"{self.app_key}",
113+
}
114+
response_data = self.http_client.post(
115+
url, json=request.model_dump(mode="json"), headers=headers
116+
)
117+
return BillManagerCancelInvoiceResponse(**response_data)
118+
119+
def cancel_bulk_invoice(
120+
self, request: BillManagerCancelBulkInvoiceRequest
121+
) -> BillManagerCancelInvoiceResponse:
122+
"""Cancel multiple invoices via Bill Manager."""
123+
self._ensure_app_key()
124+
url = "/v1/billmanager-invoice/cancel-bulk-invoices"
125+
headers = {
126+
"Authorization": f"Bearer {self.token_manager.get_token()}",
127+
"Content-Type": "application/json",
128+
"appKey": f"{self.app_key}",
129+
}
130+
response_data = self.http_client.post(
131+
url, json=request.model_dump(mode="json"), headers=headers
132+
)
133+
return BillManagerCancelInvoiceResponse(**response_data)

0 commit comments

Comments
 (0)