(20250102) Alerts on payment events.

This commit is contained in:
2025-01-02 11:53:13 +00:00
parent fd2a1ef6d1
commit cb8e322c10
5 changed files with 57 additions and 14 deletions
+2 -2
View File
@@ -46,7 +46,7 @@ from utils_v2.api.codes import StatusCodes
from icecream import IceCreamDebugger from icecream import IceCreamDebugger
# To work with datatypes: # To work with datatypes:
from typing import List from typing import List, Literal
# ***************************************************************************************************************** # *****************************************************************************************************************
@@ -141,7 +141,7 @@ class CoreBaseModel:
self, self,
message: str, message: str,
session_token = None, session_token = None,
alert_type = "error" alert_type: Literal["info", "warn", "error"] = "error"
): ):
""" """
@@ -351,8 +351,6 @@ class PaymentsController(CoreAuthTokenController, ABC):
session_token = session_token session_token = session_token
) )
print("RECEIPT ADD SQL JSON:", json.to_string(sql_json, default=str))
# Return the response: # Return the response:
if sql_json["status"] == 1: return True if sql_json["status"] == 1: return True
else: return False else: return False
@@ -296,11 +296,11 @@ class SafaricomMPesaExpressPaymentsController(PaymentsController):
code_map = { code_map = {
0: { 0: {
"status": "settled", "status": "settled",
"message": "Payment successful :)" "message": "Payment successful (0)."
}, # ... Success }, # ... Success
1037: { 1037: {
"status": "failed", "status": "failed",
"message": "The payment gateway could not reach your customer." "message": "The payment gateway could not reach your customer (1037)."
}, # ... DS Timeout. User could not be reached. }, # ... DS Timeout. User could not be reached.
1025: { 1025: {
"status": "failed", "status": "failed",
@@ -312,23 +312,23 @@ class SafaricomMPesaExpressPaymentsController(PaymentsController):
}, # ... System error while trying to send the push request. }, # ... System error while trying to send the push request.
1032: { 1032: {
"status": "rejected", "status": "rejected",
"message": "Your customer declined the payment request." "message": "Your customer declined the payment request (1032)."
}, # ... Request Cancelled by the user. }, # ... Request Cancelled by the user.
1: { 1: {
"status": "failed", "status": "failed",
"message": "Your customer has insufficient balance." "message": "Your customer has insufficient balance (1)."
}, # ... The user has insufficient balance. }, # ... The user has insufficient balance.
2001: { 2001: {
"status": "failed", "status": "failed",
"message": "The payment gateway says your credentials are invalid." "message": "The payment gateway says your credentials are invalid (2001)."
}, # ... Invalid credentials of the initiator. }, # ... Invalid credentials of the initiator.
1019: { 1019: {
"status": "failed", "status": "failed",
"message": "The transaction expired before your customer processed it." "message": "The transaction expired before your customer processed it (1019)."
}, # ... Transaction expired. }, # ... Transaction expired.
1001: { 1001: {
"status": "failed", "status": "failed",
"message": "Your customer is already in the middle of some transaction on the payment gateway." "message": "Your customer is already in the middle of some transaction on the payment gateway (1001)."
}, # ... The payer is already making some transaction. }, # ... The payer is already making some transaction.
} }
@@ -366,9 +366,15 @@ class SafaricomMPesaExpressPaymentsController(PaymentsController):
client_reference_id = pg_reference_id client_reference_id = pg_reference_id
) )
# Send an alert for debugging:
await self.send_alert(
payment.to_markdown(include_events = True),
alert_type = "info"
)
# For when the payment is successful: # For when the payment is successful:
if pg_result_code in [0]: if pg_result_code in [0]:
await self.add_receipt( receipt_added = await self.add_receipt(
sql_conn = sql_conn, sql_conn = sql_conn,
mongo_data_conn = mongo_data_conn, mongo_data_conn = mongo_data_conn,
payment = payment, payment = payment,
+41
View File
@@ -40,6 +40,7 @@ from pydantic import BaseModel, Field, field_validator, PastDatetime, AwareDatet
from typing import Optional, Literal, Union, List, Any from typing import Optional, Literal, Union, List, Any
# My utils: # My utils:
from utils_v2.string import json
from utils_v2.string import regex from utils_v2.string import regex
from utils_v2.date_time import date_time from utils_v2.date_time import date_time
@@ -252,6 +253,19 @@ class PaymentEvent(BaseModel):
def parse_date_time(cls, value): def parse_date_time(cls, value):
return date_time.parse_date_time(input_value = value, timezone = date_time.TIMEZONE_UTC) return date_time.parse_date_time(input_value = value, timezone = date_time.TIMEZONE_UTC)
# ┏┓ ┏┓
# ┃ ┓┏┏╋┏┓┏┳┓ ┣ ┓┏┏┓┏┏
# ┗┛┗┻┛┗┗┛┛┗┗ ┻ ┗┻┛┗┗┛
def to_markdown(self):
message = f"Time: `{self.eventTs}`\n"
message += f"Brief: `{self.message}`\n"
message += f"initialized by PG: `{self.initByPG}`\n"
message += "```\n"
message += json.to_string(self.payload, default = str)
message += "\n```"
return message
# --------------------------------------------------------------------------------------------------------------------- # ---------------------------------------------------------------------------------------------------------------------
@@ -373,6 +387,7 @@ class CorePaymentModel(BaseModel):
"customer": self.customer.model_dump(), "customer": self.customer.model_dump(),
"ts": self.ts.isoformat(), "ts": self.ts.isoformat(),
"lastEventTs": self.lastEventTs, "lastEventTs": self.lastEventTs,
"lastEventMessage": self.lastEventMessage,
"lastPaymentStatus": self.lastPaymentStatus, "lastPaymentStatus": self.lastPaymentStatus,
"amount": self.amount, "amount": self.amount,
"currencyCode": self.currencyCode, "currencyCode": self.currencyCode,
@@ -435,6 +450,32 @@ class CorePaymentModel(BaseModel):
if value is None: value = [] if value is None: value = []
return value return value
# ┏┓ ┏┓
# ┃ ┓┏┏╋┏┓┏┳┓ ┣ ┓┏┏┓┏┏
# ┗┛┗┻┛┗┗┛┛┗┗ ┻ ┗┻┛┗┗┛
def to_markdown(self, include_events: bool = False):
# Build the base message:
message = f"*PAYMENT RECORD*:\n\n"
message += f"Requested `{self.currencyCode} {self.amount}` from the user identified by/as:\n"
message += "```\n"
message += json.to_string(self.customer.model_dump(), default = str)
message += "\n```\n\n"
message += f"Last Status: `{self.lastPaymentStatus}`\n"
message += f"Last Message: `{self.lastEventMessage}`\n\n"
# Build the events (if asked):
if include_events:
message += "Here are all the events for your reference:\n\n"
for index, event in enumerate(self.events):
message += f"*EVENT {index:0>2}*.\n"
message += event.to_markdown()
message += "\n"
# Done here:
return message
# ***************************************************************************************************************** # *****************************************************************************************************************
# ***** **** # ***** ****
@@ -339,8 +339,6 @@ class SafaricomMPesaExpress:
"TransactionDesc": description[:13] if len(description) > 13 else description "TransactionDesc": description[:13] if len(description) > 13 else description
} }
print("HEADERS:", input_headers)
# Make the API call: # Make the API call:
api_response = await self.__post( api_response = await self.__post(
url = r"https://api.safaricom.co.ke/mpesa/stkpush/v1/processrequest", url = r"https://api.safaricom.co.ke/mpesa/stkpush/v1/processrequest",