Skip to main content

SendPaymentConfirmation Lambda Function

Quick Reference

  • Function Name: payment3-send-payment-confirmation-${BRANCH}
  • Handler: send_confirmation_email.lambda_handler
  • Runtime: Python 3.13 (Docker Image)
  • Trigger: API Gateway (POST /send_confirmation_email)
  • Timeout: 60 seconds (default)
  • Template.yaml: Lines 662-697

Function Overview

The SendPaymentConfirmation function sends payment confirmation emails to customers after successful payment. It checks if an order is paid before sending the email notification. This function is called via API Gateway and validates payment status before proceeding.

Entry Point

File: functions/processPaidOrder/send_confirmation_email.py
Handler: lambda_handler(event, context)

def lambda_handler(event, context):
body = json.loads(event["body"])
orderId = body["orderId"]
processor = SendConfimationEmail(orderId=orderId)
processor.send_notification()
return {"statusCode": 200, "body": json.dumps({"message": "success"})}

Event Structure

API Gateway Event

Path: POST /send_confirmation_email
Auth: NONE (public endpoint)

Request Body (JSON):

{
"orderId": "492500004152"
}

Example Event:

{
"body": "{\"orderId\": \"492500004152\"}"
}

Response (Success - Order Paid):

{
"statusCode": 200,
"body": "{\"message\": \"success\", \"isPaid\": true}"
}

Response (Success - Order Not Paid):

{
"statusCode": 200,
"body": "{\"message\": \"Email not sent - order is not paid\", \"isPaid\": false}"
}

Response (Error):

{
"statusCode": 500,
"body": "{\"error\": \"error message\"}"
}

Core Classes

SendConfimationEmail

Main processor class for sending payment confirmation emails.

Initialization:

processor = SendConfimationEmail(orderId="492500004152")

Properties:

  • order (cached_property): Retrieves order data from OrderTable

    @cached_property
    def order(self) -> dict:
    try:
    return next(OrderTable.query(self.orderId)).data
    except StopIteration:
    raise ValueError(f"Order {self.orderId} not found")
  • success (property): Checks if order payment is successful

    @property
    def success(self) -> bool:
    if not self.order.get("payment"):
    return False
    return self.order["payment"]["isPaid"]

Methods:

  • send_notification(): Sends email notification if order is paid
    def send_notification(self):
    if not self.success:
    print(f"Order {self.orderId} is not paid, skipping email")
    return

    user_email = self.order.get("shipping", {}).get("shippingEmail")
    if not user_email:
    print(f"No email found for order {self.orderId}")
    return

    email_sender = Email(self.order)
    email_sender._send_email(user_email)

DynamoDB Tables

OrderTable

Table Name: order-table-dev (shared across branches)

Access Pattern: Query by orderId (hash key)

Schema:

  • orderId (hash_key): Order identifier
  • data (JSON): Order data including payment information
  • payment.isPaid (boolean): Payment success status

Example Query:

from src.tables.orderTable import OrderTable

try:
order_record = next(OrderTable.query(orderId))
order_data = order_record.data
is_paid = order_data.get("payment", {}).get("isPaid", False)
except StopIteration:
# Order not found
pass

Process Flow

  1. Receive API Request: Lambda receives POST request with orderId in body
  2. Parse Event: Extract orderId from JSON body
  3. Initialize Processor: Create SendConfimationEmail instance
  4. Check Payment Status: Verify order.payment.isPaid is True
  5. Skip if Unpaid: If order is not paid, return early with message
  6. Extract Email: Get shipping.shippingEmail from order data
  7. Send Email: Use Email class to send confirmation email
  8. Return Success: Return HTTP 200 with success message

Error Handling

  • Order Not Found: Raises ValueError if order doesn't exist in OrderTable
  • No Email Address: Logs warning and returns early if no email found
  • Email Send Failure: Exceptions are caught and logged, then re-raised
  • Payment Not Completed: Returns early with informative message

Lambda Invocations

Invoked Functions

None - This function is a standalone email sender.

IAM Policies

Required Permissions:

  • DynamoDBReadPolicy on order-table-dev
  • LambdaInvokePolicy on payment3-check-status-${BRANCH} (optional, for status verification)
  • SESCrudPolicy on * (for sending emails)
  • SNS:Publish on * (for notifications)
  • DynamoDBCrudPolicy on EmailLogTable (for logging email attempts)

Environment Variables

  • BRANCH: Deployment branch name (default: "dev")

Dependencies

  • src.tables.orderTable.OrderTable: Order data access
  • src.notifications.sendEmail.Email: Email sending functionality
  • functools.cached_property: Property caching
  • datetime.datetime: Timestamp handling
  • json: JSON parsing

Testing

Local Testing:

if __name__ == "__main__":
ORDER_ID = "492500004152"
test_events = {"body": json.dumps({"orderId": ORDER_ID})}
lambda_handler(test_events, {})

Test Cases:

  1. Order exists and is paid → Email sent successfully
  2. Order exists but not paid → Early return with message
  3. Order not found → ValueError raised
  4. Order has no email → Warning logged, early return
  • ProcessPaidOrder: Processes paid orders and may trigger email sending
  • CheckStatus: Verifies payment status (can be invoked for verification)

Notes

  • This function only sends emails for paid orders
  • Email address is extracted from order.shipping.shippingEmail
  • If no email is found, the function returns early without error
  • Payment status is determined from order.payment.isPaid field
  • Email sending is handled by the Email class which logs to EmailLogTable