You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

AWS Lambda对接Watson Webhook:Postman调用报交易类型无效

AWS Lambda函数Postman调用报错:无效交易类型问题排查与修复

问题描述

我开发了一款基于Python的AWS Lambda函数,用于存储银行用户账户信息及实现用户间、用户与子用户间的交易功能,计划通过Webhook集成至IBM Watson Assistant。该函数在AWS云环境内测试运行正常,但使用Postman调用时,即便传入如下正确参数:

{
"input_json": {
"transaction_type": "self_transfer",
"user_name": "Vivek kaushal",
"amount": 100
}
}
仍返回错误:{"error": "Invalid transaction type. Please provide a valid 'transaction_type'."}

对应的Lambda代码如下:

import json
import boto3

s3 = boto3.resource(service_name='s3',
                    region_name='ap-south-1',
                    aws_access_key_id="*****************",
                    aws_secret_access_key="******************************")

bucket_name = 'bank.users'
file_key = 'user_details.json'


def get_file_object():
    try:
        obj = s3.Object(bucket_name, file_key)
        file_content = obj.get()['Body'].read().decode('utf-8')
        file_obj = json.loads(file_content)
        return file_obj
    except Exception as e:
        print(f"Error loading file from S3: {str(e)}")
        return None


def save_file_object(file_obj):
    try:
        obj = s3.Object(bucket_name, file_key)
        obj.put(Body=json.dumps(file_obj))
    except Exception as e:
        print(f"Error saving file to S3: {str(e)}")


def transfer_money_within_user(args):
    # Load the data from the JSON file
    file_obj = get_file_object()
    if file_obj is None:
        return {
            'error': "Failed to load user details from S3."
        }

    user_name = args.get('user_name')
    sub_user_name = args.get('sub_user_name')
    amount = args.get('amount')

    # Search for the user and sub user
    for user in file_obj['users']:
        if user['user_name'] == user_name:
            sub_users = user.get('sub_users', [])
            # Search for the sub user based on the name
            for sub_user in sub_users:
                if sub_user['sub_user_name'] == sub_user_name:
                    user_balance = user['bank_details']['balance']
                    # Check if the user has sufficient balance
                    if user_balance >= amount:
                        # Update the sub user balance
                        sub_user['bank_details']['balance'] += amount

                        # Update the user balance
                        user['bank_details']['balance'] -= amount

                        # Save the updated data to S3
                        save_file_object(file_obj)

                        # Return the updated data as a JSON response
                        return {
                            'message': f"Money transferred successfully from user '{user_name}' to sub user '{sub_user_name}'.",
                            'remaining_balance': user['bank_details']['balance']
                        }
                    else:
                        return {
                            'error': f"Insufficient balance in user '{user_name}' to transfer the amount.",
                            'current_balance': user['bank_details']['balance']
                        }

            # If sub user not found, ask if the user wants to add a new sub user
            return {
                'error': "Sub user not found. Do you want to add a new sub user?",
                'add_new_sub_user': True
            }

    # If user not found, return an error message
    return {
        'error': f"No user found with the name '{user_name}'."
    }


def transfer_money_between_users(args):
    # Load the data from the JSON file
    file_obj = get_file_object()
    if file_obj is None:
        return {
            'error': "Failed to load user details from S3."
        }

    sender_user_name = args.get('sender_user_name')
    recipient_user_name = args.get('recipient_user_name')
    amount = args.get('amount')

    # Search for the sender user and recipient user
    sender_user = None
    recipient_user = None

    for user in file_obj['users']:
        if user['user_name'] == sender_user_name:
            sender_user = user
        elif user['user_name'] == recipient_user_name:
            recipient_user = user

    # Check if both sender user and recipient user are found
    if sender_user and recipient_user:
        sender_user_balance = sender_user['bank_details']['balance']

        # Check if the sender user has sufficient balance
        if sender_user_balance >= amount:
            # Update the sender user balance
            sender_user['bank_details']['balance'] -= amount

            # Update the recipient user balance
            recipient_user['bank_details']['balance'] += amount

            # Save the updated data to S3
            save_file_object(file_obj)

            # Return the updated data as a JSON response
            return {
                'message': f"Money transferred successfully from user '{sender_user_name}' to user '{recipient_user_name}'.",
                'remaining_balance': sender_user['bank_details']['balance']
            }
        else:
            # If sender user does not have sufficient balance, return an error message
            return {
                'error': f"Insufficient balance in user '{sender_user_name}' to transfer the amount.",
                'current_balance': sender_user['bank_details']['balance']
            }
    else:
        # If either sender user or recipient user is not found, return an error message
        error_msg = ""
        if not sender_user:
            error_msg += f"No sender user found with the name '{sender_user_name}'.\n"
        if not recipient_user:
            error_msg += f"No recipient user found with the name '{recipient_user_name}'.\n"
        return {
            'error': error_msg.strip()
        }


def transfer_money_to_self(args):
    # Load the data from the JSON file
    file_obj = get_file_object()
    if file_obj is None:
        return {
            'error': "Failed to load user details from S3."
        }

    user_name = args.get('user_name')
    amount = args.get('amount')

    # Search for the user
    for user in file_obj['users']:
        if user['user_name'] == user_name:
            user_balance = user['bank_details']['balance']
            # Check if the user has sufficient balance
            if user_balance >= amount:
                # Update the user balance
                user['bank_details']['balance'] -= amount

                # Save the updated data to S3
                save_file_object(file_obj)

                # Return the updated data as a JSON response
                return {
                    'message': f"Money transferred successfully from user '{user_name}' to itself.",
                    'remaining_balance': user['bank_details']['balance']
                }
            else:
                return {
                    'error': f"Insufficient balance in user '{user_name}' to transfer the amount.",
                    'current_balance': user['bank_details']['balance']
                }

    # If user not found, return an error message
    return {
        'error': f"No user found with the name '{user_name}'."
    }


def lambda_handler(event, context):
    input_json = event.get('input_json', {})
    transaction_type = str(input_json.get('transaction_type'))

    if transaction_type == 'user':
        sender_user_name = str(input_json.get('sender_user_name'))
        recipient_user_name = str(input_json.get('recipient_user_name'))
        amount = float(input_json.get('amount'))

        # Invoke the transfer_money_between_users function with the parameters
        result = transfer_money_between_users({
            'sender_user_name': sender_user_name,
            'recipient_user_name': recipient_user_name,
            'amount': amount
        })

    elif transaction_type == 'sub_user':
        user_name = str(input_json.get('user_name'))
        sub_user_name = str(input_json.get('sub_user_name'))
        amount = float(input_json.get('amount'))

        # Invoke the transfer_money_within_user function with the parameters
        result = transfer_money_within_user({
            'user_name': user_name,
            'sub_user_name': sub_user_name,
            'amount': amount
        })

    elif transaction_type == 'add_sub_user':
        user_name = str(input_json.get('user_name'))
        sub_user_name = str(input_json.get('sub_user_name'))
        balance = float(input_json.get('balance', 0))
        account_number = str(input_json.get('account_number'))
        mobile_number = str(input_json.get('mobile_number'))
        bank = str(input_json.get('bank'))
        ifsc_code = str(input_json.get('ifsc_code'))

        # Load the data from the JSON file
        file_obj = get_file_object()
        if file_obj is None:
            return {
                'statusCode': 500,
                'body': json.dumps({
                    'error': "Failed to load user details from S3."
                })
            }

        # Search for the user based on the name
        for user in file_obj['users']:
            if user['user_name'] == user_name:
                sub_users = user.get('sub_users', [])
                # Check if the sub user already exists
                if any(sub_user['sub_user_name'] == sub_user_name for sub_user in sub_users):
                    return {
                        'statusCode': 400,
                        'body': json.dumps({
                            'error': f"Sub user '{sub_user_name}' already exists for user '{user_name}'."
                        })
                    }
                else:
                    # Add the new sub user with bank details
                    new_sub_user = {
                        'sub_user_name': sub_user_name,
                        'bank_details': {
                            'balance': balance,
                            'account_number': account_number,
                            'mobile_number': mobile_number,
                            'bank': bank,
                            'ifsc_code': ifsc_code
                        }
                    }
                    sub_users.append(new_sub_user)

                    # Save the updated data to S3
                    save_file_object(file_obj)

                    return {
                        'statusCode': 200,
                        'body': json.dumps({
                            'message': f"New sub user '{sub_user_name}' added for user '{user_name}' with balance {balance}."
                        })
                    }

        # If user not found, return an error message
        return {
            'statusCode': 404,
            'body': json.dumps({
                'error': f"No user found with the name '{user_name}'."
            })
        }

    elif transaction_type == 'self_transfer':
        user_name = str(input_json.get('user_name'))
        amount = float(input_json.get('amount'))

        # Invoke the transfer_money_to_self function with the parameters
        result = transfer_money_to_self({
            'user_name': user_name,
            'amount': amount
        })

    else:
        return {
            'statusCode': 400,
            'body': json.dumps({
                'error': "Invalid transaction type. Please provide a valid 'transaction_type'."
            })
        }

    return {
        'statusCode': 200,
        'body': json.dumps(result)
    }

问题根源

AWS控制台测试Lambda时,event参数直接包含input_json顶级字段;但通过Postman或外部Webhook调用Lambda URL时,请求的JSON体被Lambda封装在event['body']字段中,而非直接作为event的顶级属性。

代码中input_json = event.get('input_json', {})在Postman调用时会获取到空字典,导致transaction_type被转为空字符串,最终触发无效交易类型的错误分支。

修复方案

修改lambda_handler函数开头逻辑,兼容两种请求结构:

def lambda_handler(event, context):
    # 处理Postman等外部调用:解析body中的JSON内容
    if 'body' in event:
        try:
            event = json.loads(event['body'])
        except json.JSONDecodeError:
            return {
                'statusCode': 400,
                'body': json.dumps({
                    'error': "请求体JSON格式无效"
                })
            }
    
    input_json = event.get('input_json', {})
    transaction_type = str(input_json.get('transaction_type'))
    
    # 后续原有逻辑保持不变...

额外优化建议

  • 移除代码中硬编码的AWS密钥,改用Lambda执行角色的权限访问S3,提升安全性。
  • 增加transaction_type为空的判断,返回更明确的错误提示。
  • 确认transfer_money_to_self函数的业务合理性,通常"转账给自己"属于冗余操作,可根据需求调整逻辑。

内容的提问来源于stack exchange,提问作者Shaik Saad Abdul Tawwab

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 07:07:02