Create handle_order Lambda function

In this step, we will create a new handle_order Lambda function using a SAM template.

Preparation

  1. Open template.yaml in the source code you downloaded before.

    • Comment this code block.

      # BookApiDeployment:
      #   Type: AWS::ApiGateway::Deployment
      #   Properties:
      #     RestApiId: !Ref BookApi
      #   DependsOn:
      #     - BookApiGet
      #     - BookApiCreate
      #     - BookApiDelete
      #     - LoginApi
      #     - RegisterApi
      #     - ConfirmApi
      #     - FCAJCheckoutOrderApi
      #     - FCAJOrderManagementApi
      
      BookApiStage:
        Type: AWS::ApiGateway::Stage
        Properties:
          RestApiId: !Ref BookApi
          StageName: !Ref stage
      #     DeploymentId: !Ref BookApiDeployment
      

      Comment BookApiDeployment

  2. Run the below commands.

    sam validate
    sam build
    

    SAM validate and build

  3. Deploy the updated stack.

    sam deploy
    

    SAM deploy

  4. Review the CloudFormation changeset and confirm the deployment by typing y.

    CloudFormation changeset and deploy confirmation

  5. Wait for the deployment to complete.

    Deploy complete

Create FCAJHandleOrder function

  1. Open template.yaml in the source code you downloaded before.

    • Add the following parameter.

      handleOrderPathPart:
        Type: String
        Default: handle
      

      Add handleOrderPathPart parameter

    • Add the following scripts below to create FCAJHandleOrder function.

      FCAJHandleOrderResource:
        Type: AWS::ApiGateway::Resource
        Properties:
          RestApiId: !Ref BookApi
          ParentId: !Ref FCAJCheckoutOrderResource
          PathPart: !Ref handleOrderPathPart
      
      FCAJHandleOrderFunction:
        Type: AWS::Serverless::Function
        Properties:
          CodeUri: fcaj-book-shop/handle_order
          Handler: handle_order.lambda_handler
          Runtime: python3.13
          FunctionName: handle_order
          Environment:
            Variables:
              ORDER_TABLE_NAME: !Ref orderTable
              SQS_QUEUE_URL: !Ref checkoutQueueUrl
          Architectures:
            - x86_64
          Policies:
            - Statement:
                - Sid: VisualEditor0
                  Effect: Allow
                  Action:
                    - dynamodb:PutItem
                    - dynamodb:BatchWriteItem
                  Resource:
                    - !Sub "arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/${orderTable}"
                - Sid: VisualEditor1
                  Effect: Allow
                  Action:
                    - sqs:*
                  Resource:
                    - !Sub "arn:aws:sqs:${AWS::Region}:${AWS::AccountId}:${checkoutQueueName}"
      

      Add FCAJHandleOrderResource and Function

      FCAJHandleOrderApiOptions:
        Type: AWS::ApiGateway::Method
        Properties:
          HttpMethod: OPTIONS
          RestApiId: !Ref BookApi
          ResourceId: !Ref FCAJHandleOrderResource
          AuthorizationType: NONE
          Integration:
            Type: MOCK
            IntegrationResponses:
              - StatusCode: "200"
                ResponseParameters:
                  method.response.header.Access-Control-Allow-Origin: "'*'"
                  method.response.header.Access-Control-Allow-Methods: "'OPTIONS,POST,GET,DELETE'"
                  method.response.header.Access-Control-Allow-Headers: "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token'"
          MethodResponses:
            - StatusCode: "200"
              ResponseParameters:
                method.response.header.Access-Control-Allow-Origin: true
                method.response.header.Access-Control-Allow-Methods: true
                method.response.header.Access-Control-Allow-Headers: true
      

      Add FCAJHandleOrderApiOptions

      FCAJHandleOrderApi:
        Type: AWS::ApiGateway::Method
        Properties:
          HttpMethod: POST
          RestApiId: !Ref BookApi
          ResourceId: !Ref FCAJHandleOrderResource
          AuthorizationType: NONE
          Integration:
            Type: AWS_PROXY
            IntegrationHttpMethod: POST # For Lambda integrations, you must set the integration method to POST
            Uri: !Sub >-
              arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${FCAJHandleOrderFunction.Arn}/invocations
          MethodResponses:
            - StatusCode: "200"
              ResponseParameters:
                method.response.header.Access-Control-Allow-Origin: true
                method.response.header.Access-Control-Allow-Methods: true
                method.response.header.Access-Control-Allow-Headers: true
      
      FCAJHandleOrderApiInvokePermission:
        Type: AWS::Lambda::Permission
        Properties:
          FunctionName: !Ref FCAJHandleOrderFunction
          Action: lambda:InvokeFunction
          Principal: apigateway.amazonaws.com
          SourceAccount: !Ref "AWS::AccountId"
      

      Add FCAJHandleOrderApi and InvokePermission

  2. The directory structure is as follows.

    fcaj-book-shop
    ├── fcaj-book-shop
    │   ├── checkout_order
    │   │   └── checkout_order.py
    │   ├── order_management
    │   │   └── order_management.py
    │   ├── handle_order
    │   │   └── handle_order.py
    │   ├── ...
    └── template.yaml
    
    • Create handle_order folder in fcaj-book-shop/fcaj-book-shop/ folder.

    • Create handle_order.py file and copy the following code to it.

      import json
      import boto3
      import os
      
      headers = {
          "Content-Type": "application/json",
          "Access-Control-Allow-Origin": "*",
          "Access-Control-Allow-Methods": "OPTIONS,POST,GET,DELETE",
          "Access-Control-Allow-Headers": "Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token"
      }
      
      dynamodb = boto3.resource('dynamodb')
      sqs = boto3.client('sqs')
      
      # Define the DynamoDB table name and SQS queue URL
      table_name = os.getenv('ORDER_TABLE_NAME')
      queue_url = os.getenv('SQS_QUEUE_URL')
      
      
      def lambda_handler(event, context):
          # Get product body info from the event
          products = json.loads(event['body'])
          books = products['books']
          receipt_handle = products['receiptHandle']
      
          # Write product info to DynamoDB
          table = dynamodb.Table(table_name)
          try:
              for book in books:
                  data = {
                      'id': products['id'],
                      'book_id': book['id'],
                      'name': book['name'],
                      'qty': book['qty'],
                      'price': str(products['price'])
                  }
      
                  table.put_item(Item=data)
      
          except Exception as e:
              print(f"Error writing to DynamoDB: {e}")
              raise Exception(f"Error writing to DynamoDB: {e}")
      
          # Delete message from SQS
          try:
              sqs.delete_message(
                  QueueUrl=queue_url,
                  ReceiptHandle=receipt_handle
              )
          except Exception as e:
              print(f"Error deleting message from SQS: {e}")
              raise Exception(f"Error deleting message from SQS: {e}")
      
          return {
              'statusCode': 200,
              'headers': headers,
              'body': json.dumps('Successfully handled order')
          }
      

      handle_order.py

  3. Uncomment this code block.

    BookApiDeployment:
      Type: AWS::ApiGateway::Deployment
      Properties:
        RestApiId: !Ref BookApi
      DependsOn:
        - BookApiGet
        - BookApiCreate
        - BookApiDelete
        - LoginApi
        - RegisterApi
        - ConfirmApi
        - FCAJCheckoutOrderApi
        - FCAJOrderManagementApi
        - FCAJHandleOrderApi
    
    BookApiStage:
      Type: AWS::ApiGateway::Stage
      Properties:
        RestApiId: !Ref BookApi
        StageName: !Ref stage
        DeploymentId: !Ref BookApiDeployment
    

    Uncomment BookApiDeployment

  4. Run the below commands.

    sam validate
    sam build
    

    SAM validate and build

  5. Deploy the updated stack.

    sam deploy
    

    SAM deploy with FCAJHandleOrder

  6. Wait for the deployment to complete.

    Deploy complete

Check the creation

  1. Open Amazon API Gateway console.

    • Click fcaj-serverless-api. API Gateway list
    • Click Resources on the left menu.
    • Check /handle just created under /order. API Gateway Resources
  2. Open Amazon Lambda console.

    • Click Functions on the left menu.
    • Choose handle_order function. Lambda Functions list
    • At handle_order page, check the function that just created. handle_order function detail