

**终止支持通知：** AWS 将于 2026 年 10 月 30 日终止对亚马逊 Pinpoint 的支持。2026 年 10 月 30 日之后，您将不再能够访问 Amazon Pinpoint 控制台或 Amazon Pinpoint 资源（端点、分段、活动、旅程和分析）。有关更多信息，请参阅 [Amazon Pinpoint 终止支持](https://docs.aws.amazon.com/console/pinpoint/migration-guide)。**注意：** APIs 与短信相关、语音、移动推送、OTP 和电话号码验证不受此更改的影响，并受 AWS 最终用户消息的支持。

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# 创建 Lambda 函数以用于 Amazon Pinpoint 短信收发
<a name="tutorials-two-way-sms-part-3"></a>

本节将向您介绍如何创建和配置两个 Lambda 函数以用于 Amazon Pinpoint 短信收发。稍后，您将设置 API Gateway 和 Amazon Pinpoint 以在发生特定事件时调用这些函数。这两个函数会在您指定的 Amazon Pinpoint 项目中创建和更新端点。第一个函数还使用电话号码验证功能。

## 创建可验证客户信息并可创建端点的函数
<a name="tutorials-two-way-sms-part-3-create-register-function"></a>

第一个函数从您的注册表单（从 Amazon API Gateway 接收）中获取输入。它使用这些信息，通过使用 Amazon Pinpoint 的[电话号码验证](https://docs.aws.amazon.com/pinpoint/latest/developerguide/validate-phone-numbers.html)特征来获取有关客户电话号码的信息。然后，该函数使用验证的数据在您指定的 Amazon Pinpoint 项目中创建一个新的端点。默认情况下，该函数创建的端点会选择不接收您的未来通信，但此状态可通过第二个函数进行更改。最后，此函数向客户发送一条消息，要求他们验证是否希望接收来自您的短信通信。

**创建 Lambda 函数**

1. 打开 AWS Lambda 控制台，网址为[https://console.aws.amazon.com/lambda/](https://console.aws.amazon.com/lambda/)。

1. 选择**创建函数**。

1. 在**创建函数**下，选择**使用蓝图**。

1. 在搜索字段中，输入 **hello**，然后按 Enter。在结果列表中，选择 `hello-world` Node.js 函数，如下图所示。  
![\[显示已选定“使用蓝图”的“创建函数”页面。\]](http://docs.aws.amazon.com/zh_cn/pinpoint/latest/userguide/images/SMS_Reg_Tutorial_LAM_Step1.5.png)

1. 在**基本信息**中，执行以下操作：
   + 对于**名称**，输入函数的名称，如 **RegistrationForm**。
   + 对于**角色**，选择**选择现有角色**。
   + 对于**现有角色**，请选择您在创建 [IAM 角色中创建的**SMSRegistration表单**角色](tutorials-two-way-sms-part-2.md#tutorials-two-way-sms-part-2-create-role)。

   完成后，选择**创建函数**。

1. 对于**代码源**，删除代码编辑器中的示例函数，然后粘贴以下代码：

   ```
   import { PinpointClient, PhoneNumberValidateCommand, UpdateEndpointCommand, SendMessagesCommand } from "@aws-sdk/client-pinpoint"; // ES Modules import
   const pinClient = new PinpointClient({region: process.env.region});  
   
   // Make sure the SMS channel is enabled for the projectId that you specify.
   // See: https://docs.aws.amazon.com/pinpoint/latest/userguide/channels-sms-setup.html
   var projectId = process.env.projectId;
   
   // You need a dedicated long code in order to use two-way SMS. 
   // See: https://docs.aws.amazon.com/pinpoint/latest/userguide/channels-voice-manage.html#channels-voice-manage-request-phone-numbers
   var originationNumber = process.env.originationNumber;
   
   // This message is spread across multiple lines for improved readability.
   var message = "ExampleCorp: Reply YES to confirm your subscription. 2 msgs per "
               + "month. No purchase req'd. Msg&data rates may apply. Terms: "
               + "example.com/terms-sms";
               
   var messageType = "TRANSACTIONAL";
   
   export const handler = async (event, context) => {
     console.log('Received event:', event);
     await validateNumber(event);
   };
   
   async function validateNumber (event) {
     var destinationNumber = event.destinationNumber;
     if (destinationNumber.length == 10) {
       destinationNumber = "+1" + destinationNumber;
     }
     var params = {
       NumberValidateRequest: {
         IsoCountryCode: 'US',
         PhoneNumber: destinationNumber
       }
     };
     try{
       const PhoneNumberValidateresponse = await pinClient.send( new  PhoneNumberValidateCommand(params));
       console.log(PhoneNumberValidateresponse);
        if (PhoneNumberValidateresponse['NumberValidateResponse']['PhoneTypeCode'] == 0) {
           await createEndpoint(PhoneNumberValidateresponse, event.firstName, event.lastName, event.source);
           
         } else {
           console.log("Received a phone number that isn't capable of receiving "
                      +"SMS messages. No endpoint created.");
         }
     }catch(err){
       console.log(err);
     }
   }
   
   async function createEndpoint(data, firstName, lastName, source) {
     var destinationNumber = data['NumberValidateResponse']['CleansedPhoneNumberE164'];
     var endpointId = data['NumberValidateResponse']['CleansedPhoneNumberE164'].substring(1);
     
     var params = {
       ApplicationId: projectId,
       // The Endpoint ID is equal to the cleansed phone number minus the leading
       // plus sign. This makes it easier to easily update the endpoint later.
       EndpointId: endpointId,
       EndpointRequest: {
         ChannelType: 'SMS',
         Address: destinationNumber,
         // OptOut is set to ALL (that is, endpoint is opted out of all messages)
         // because the recipient hasn't confirmed their subscription at this
         // point. When they confirm, a different Lambda function changes this 
         // value to NONE (not opted out).
         OptOut: 'ALL',
         Location: {
           PostalCode:data['NumberValidateResponse']['ZipCode'],
           City:data['NumberValidateResponse']['City'],
           Country:data['NumberValidateResponse']['CountryCodeIso2'],
         },
         Demographic: {
           Timezone:data['NumberValidateResponse']['Timezone']
         },
         Attributes: {
           Source: [
             source
           ]
         },
         User: {
           UserAttributes: {
             FirstName: [
               firstName
             ],
             LastName: [
               lastName
             ]
           }
         }
       }
     };
     try{
       const UpdateEndpointresponse = await pinClient.send(new UpdateEndpointCommand(params));
       console.log(UpdateEndpointresponse);
       await sendConfirmation(destinationNumber);
     }catch(err){
       console.log(err);
     }  
   }
   
   async function sendConfirmation(destinationNumber) {
     var params = {
       ApplicationId: projectId,
       MessageRequest: {
         Addresses: {
           [destinationNumber]: {
             ChannelType: 'SMS'
           }
         },
         MessageConfiguration: {
           SMSMessage: {
             Body: message,
             MessageType: messageType,
             OriginationNumber: originationNumber
           }
         }
       }
     };
     try{
       const SendMessagesCommandresponse = await pinClient.send(new SendMessagesCommand(params));
       console.log("Message sent! " 
             + SendMessagesCommandresponse['MessageResponse']['Result'][destinationNumber]['StatusMessage']);
     }catch(err){
       console.log(err);
     }
   }
   ```

1. 在**环境变量**的**配置**选项卡中，依次选择**编辑**、**添加环境变量**，然后执行以下操作：
   + 在第一行创建一个包含 **originationNumber** 键值的变量。接下来，将值设置为您在[步骤 1.2](tutorials-two-way-sms-part-1.md#tutorials-two-way-sms-part-1-set-up-channel) 中收到的专用长代码的电话号码。
**注意**  
请务必包含加号 (\$1) 和电话号码的国家/地区代码。请勿包含任何其他特殊字符，如连字符 (-)、句点 (.) 或圆括号。
   + 在第二行创建一个包含 **projectId** 键值的变量。接下来，将值设置为您在[步骤 1.1](tutorials-two-way-sms-part-1.md#tutorials-two-way-sms-part-1-create-project) 中创建的项目的唯一 ID。
   + 在第三行创建一个包含 **region** 键值的变量。接下来，将值设置为您使用 Amazon Pinpoint 所在的区域，如 **us-east-1** 或 **us-west-2**。

   完成后，**Environment Variables (环境变量)** 部分应类似于下图中的示例。  
![\[originationNumber、projectId 和 region 的环境变量。\]](http://docs.aws.amazon.com/zh_cn/pinpoint/latest/userguide/images/SMS_Reg_Tutorial_LAM_Step1.7.png)

1. 在页面顶部，选择 **Save (保存)**。

### 测试此函数
<a name="tutorials-two-way-sms-part-3-create-register-function-test"></a>

创建函数后，您应对其进行测试，以确保其配置正确。此外还要确保您创建的 IAM 角色具有适当权限。

**测试此函数**

1. 选择**测试**选项卡。

1. 选择**创建新事件**，然后执行以下操作：
   + 对于**事件名称**，输入测试事件的名称，如 **MyPhoneNumber**。
   + 擦除代码编辑器中的示例代码。粘贴以下代码：

     ```
     {
       "destinationNumber": "+12065550142",
       "firstName": "Carlos",
       "lastName": "Salazar",
       "source": "Registration form test"
     }
     ```
   + 在上述代码示例中，将 `destinationNumber`、`firstName` 和 `lastName` 属性值替换为您想用于测试的值，例如您的个人联系详细信息。当您测试此函数时，它会向您在 `destinationNumber` 属性中指定的电话号码发送短信。请确保您指定的电话号码能够接收短信。
   + 选择**创建**。

1. 选择**测试**。

1. 在 **Execution result: succeeded (执行结果：成功)** 下，选择 **Details (详细信息)**。在 **Log output (日志输出)** 部分中，查看函数的输出。确保该函数运行未出现错误。

   检查与您指定的 `destinationNumber` 关联的设备，确保它收到测试消息。

1. 打开亚马逊 Pinpoint 控制台，网址为。[https://console.aws.amazon.com/pinpoint/](https://console.aws.amazon.com/pinpoint/)

1. 在**所有项目**页面上，选择您在[创建 Amazon Pinpoint 项目](tutorials-two-way-sms-part-1.md#tutorials-two-way-sms-part-1-create-project)中创建的项目。

1. 在导航窗格中，选择**客户细分**。在**客户细分**页面上，选择**创建客户细分**。

1. 在 **Segment group 1 (分段组 1)** 的 **Add filters to refine your segment (添加筛选条件以细化分段)** 下，选择 **Filter by user (按用户筛选)**。

1. 在 **“选择用户属性”** 中，选择**FirstName**。然后，对于 **Choose values (选择值)**，选择您在测试事件中指定的名字。

   **客户细分估算**部分应显示有零个合格端点，以及总共一个端点，如下图所示。这是预期结果。当函数创建一个新的端点时，该端点将选择退出。Amazon Pinpoint 中的客户细分会自动排除已选择退出的端点。  
![\[显示零端点的客户细分组。\]](http://docs.aws.amazon.com/zh_cn/pinpoint/latest/userguide/images/SMS_Reg_Tutorial_LAM_Step8.9.png)

## 创建用于选择让客户接收您的通信的函数
<a name="tutorials-two-way-sms-part-3-create-optin-function"></a>

仅当客户回复第一个函数发送的消息时才会执行第二个函数。如果客户的回复包含[启用双向短信](tutorials-two-way-sms-part-1.md#tutorials-two-way-sms-part-1-set-up-channel)中指定的关键字，则该函数将更新其端点记录，选择让客户接收未来通信。Amazon Pinpoint 还会自动使用您在[启用双向短信](tutorials-two-way-sms-part-1.md#tutorials-two-way-sms-part-1-set-up-channel)中指定的消息进行回复。

如果客户没有响应，或者使用指定关键字以外的任何内容进行响应，则什么都不会发生。客户的端点虽然仍在 Amazon Pinpoint 中，但不能被客户细分当作目标。

**创建 Lambda 函数**

1. 打开 AWS Lambda 控制台，网址为[https://console.aws.amazon.com/lambda/](https://console.aws.amazon.com/lambda/)。

1. 选择**创建函数**。

1. 在**创建函数**下，选择**蓝图**。

1. 在搜索字段中，输入 **hello**，然后按 Enter。在结果列表中，选择 `hello-world` Node.js 函数，如下图所示。选择 **Configure**（配置）。

1. 在 **Basic information**（基本信息）中，执行以下操作：
   + 对于**名称**，输入函数的名称，如 **RegistrationForm\$1OptIn**。
   + 对于**角色**，选择**选择现有角色**。
   + 对于**现有角色**，请选择您在创建 [IAM 角色中创建的 SMSRegistration表单角色](tutorials-two-way-sms-part-2.md#tutorials-two-way-sms-part-2-create-role)。

   完成后，选择**创建函数**。

1. 删除代码编辑器中的示例函数，然后粘贴以下代码：

   ```
   import { PinpointClient, UpdateEndpointCommand } from "@aws-sdk/client-pinpoint"; // ES Modules import
   
   // Create a new Pinpoint client instance with the region specified in the environment variables
   const pinClient = new PinpointClient({ region: process.env.region });
   
   // Get the Pinpoint project ID and the confirm keyword from environment variables
   const projectId = process.env.projectId;
   const confirmKeyword = process.env.confirmKeyword.toLowerCase();
   
   // This is the main handler function that is invoked when the Lambda function is triggered
   export const handler = async (event, context) => {
       console.log('Received event:', event);
   
       try {
           // Extract the timestamp, message, and origination number from the SNS event
           const timestamp = event.Records[0].Sns.Timestamp;
           const message = JSON.parse(event.Records[0].Sns.Message);
           const originationNumber = message.originationNumber;
           const response = message.messageBody.toLowerCase();
   
           // Check if the response message contains the confirm keyword
           if (response.includes(confirmKeyword)) {
               // If the confirm keyword is found, update the endpoint's opt-in status
               await updateEndpointOptIn(originationNumber, timestamp);
           }
       }catch (error) {
           console.error('An error occurred:', error);
           throw error; // Rethrow the error to handle it upstream
       }
   };
   
   // This function updates the opt-in status of a Pinpoint endpoint
   async function updateEndpointOptIn(originationNumber, timestamp) {
       // Extract the endpoint ID from the origination number
       const endpointId = originationNumber.substring(1);
   
        // Prepare the parameters for the UpdateEndpointCommand
       const params = {
           ApplicationId: projectId,
           EndpointId: endpointId,
           EndpointRequest: {
               Address: originationNumber,
               ChannelType: 'SMS',
               OptOut: 'NONE',
               Attributes: {
                   OptInTimestamp: [timestamp]
               },
           }
       };
   
       try {
           // Send the UpdateEndpointCommand to update the endpoint's opt-in status
           const updateEndpointResponse = await pinClient.send(new UpdateEndpointCommand(params));
           console.log(updateEndpointResponse);
           console.log(`Successfully changed the opt status of endpoint ID ${endpointId}`);
       } catch (error) {
           console.error('An error occurred while updating endpoint:', error);
           throw error; // Rethrow the error to handle it upstream
       }
   }
   ```

1. 在 **Environment variables (环境变量)** 下，执行以下操作：
   + 在第一行创建一个包含 **projectId** 键值的变量。接下来，将值设置为您在[创建 Amazon Pinpoint 项目](tutorials-two-way-sms-part-1.md#tutorials-two-way-sms-part-1-create-project)中创建的项目的唯一 ID。
   + 在第二行创建一个包含 **region** 键值的变量。接下来，将值设置为您使用 Amazon Pinpoint 所在的区域，如 **us-east-1** 或 **us-west-2**。
   + 在第三行创建一个包含 **confirmKeyword** 键值的变量。接下来，将值设置为您在[启用双向短信](tutorials-two-way-sms-part-1.md#tutorials-two-way-sms-part-1-set-up-channel)中创建的确认关键字。
**注意**  
关键字不区分大小写。此函数会将传入消息转换为小写字母。

   完成后，**Environment Variables (环境变量)** 部分应类似于下图中的示例。  
![\[projectId、region 和 confirmKeyword 的环境变量。\]](http://docs.aws.amazon.com/zh_cn/pinpoint/latest/userguide/images/SMS_Reg_Tutorial_LAM_Step2.7.png)

1. 在页面顶部，选择 **Save (保存)**。

### 测试此函数
<a name="tutorials-two-way-sms-part-3-create-optin-function-test"></a>

创建函数后，您应对其进行测试，以确保其配置正确。此外还要确保您创建的 IAM 角色具有适当权限。

**测试此函数**

1. 选择**测试**。

1. 在 **Configure test event (配置测试事件)** 窗口上，执行以下操作：

   1. 选择 **Create new test event**（新建测试事件）。

   1. 对于**事件名称**，输入测试事件的名称，如 **MyResponse**。

   1. 擦除代码编辑器中的示例代码。粘贴以下代码：

      ```
      {
        "Records":[
          {
            "Sns":{
              "Message":"{\"originationNumber\":\"+12065550142\",\"messageBody\":\"Yes\"}",
              "Timestamp":"2019-02-20T17:47:44.147Z"
            }
          }
        ]
      }
      ```

      在上述代码示例中，将 `originationNumber` 属性的值替换为您在测试之前的 Lambda 函数时使用的电话号码。将 `messageBody` 的值替换为您在[启用双向短信](tutorials-two-way-sms-part-1.md#tutorials-two-way-sms-part-1-enable-two-way)中指定的双向短信关键字。（可选）您可以将 `Timestamp` 的值替换为当前日期和时间。

   1. 选择**创建**。

1. 再次选择 **Test (测试)**。

1. 在 **Execution result: succeeded (执行结果：成功)** 下，选择 **Details (详细信息)**。在 **Log output (日志输出)** 部分中，查看函数的输出。确保该函数运行未出现错误。

1. 打开亚马逊 Pinpoint 控制台，网址为。[https://console.aws.amazon.com/pinpoint/](https://console.aws.amazon.com/pinpoint/)

1. 在**所有项目**页面上，选择您在[创建 Amazon Pinpoint 项目](tutorials-two-way-sms-part-1.md#tutorials-two-way-sms-part-1-create-project)中创建的项目。

1. 在导航窗格中，选择**客户细分**。在**客户细分**页面上，选择**创建客户细分**。

1. 在 **Segment group 1 (分段组 1)** 的 **Add filters to refine your segment (添加筛选条件以细化分段)** 下，选择 **Filter by user (按用户筛选)**。

1. 在 **“选择用户属性”** 中，选择**FirstName**。然后，对于 **Choose values (选择值)**，选择您在测试事件中指定的名字。

   **客户细分估算**部分应显示有一个合格端点，以及总共一个端点。

**下一步**：[设置 Amazon API Gateway](tutorials-two-way-sms-part-4.md)