我正在尝试构建一个演示 Alexa Skill,其中我使用 Customer Profile API 来获取客户详细信息,例如电子邮件等,然后我想将电子邮件 ID 保存到 dynamoDb 。我已按照文档中的所有说明进行操作,但无法使其正常工作。请查看我的代码并告诉我我做错了什么。任何帮助或新鲜的观点表示赞赏。
dBhelper.js
var AWS = require("aws-sdk");
AWS.config.update({region: "us-east-1"});
const tableName = "user-emails";
var dbHelper = function () { };
var docClient = new AWS.DynamoDB.DocumentClient();
dbHelper.prototype.addEmail = (email, userID) => {
return new Promise((resolve, reject) => {
const params = {
TableName: tableName,
Item: {
'email' : email,
'userId': userID
}
};
docClient.put(params, (err, data) => {
if (err) {
console.log("Unable to insert =>", JSON.stringify(err))
return reject("Unable to insert");
}
console.log("Saved Data, ", JSON.stringify(data));
resolve(data);
});
});
}
module.exports = new dbHelper();
index.js
//const Alexa = require('ask-sdk-core');
const Alexa = require('ask-sdk');
const dbHelper = require('./helpers/dbHelper');
const GENERAL_REPROMPT = "What would you like to do?";
const dynamoDBTableName = "user-emails";
const messages = {
WELCOME: 'Welcome to the Sample Alexa Customer Profile API Skill! You can ask for your name, your email address, or your phone number. What do you want to ask?',
WHAT_DO_YOU_WANT: 'What do you want to ask?',
NOTIFY_MISSING_PERMISSIONS: 'Please enable Customer Profile permissions in the Amazon Alexa app.',
NAME_MISSING: 'You can set your name either in the Alexa app under calling and messaging, or you can set it at Amazon.com, under log-in and security.',
EMAIL_MISSING: 'You can set your email at Amazon.com, under log-in and security.',
NUMBER_MISSING: 'You can set your phone number at Amazon.com, under log-in and security.',
NAME_AVAILABLE: 'Here is your full name: ',
EMAIL_AVAILABLE: 'Here is your email address: ',
NUMBER_AVAILABLE: 'Here is your phone number: ',
ERROR: 'Uh Oh. Looks like something went wrong.',
API_FAILURE: 'There was an error with the Alexa Customer Profile API. Please try again.',
GOODBYE: 'Bye! Thanks for using the Sample Alexa Customer Profile API Skill!',
UNHANDLED: 'This skill doesn\'t support that. Please ask something else.',
HELP: 'You can use this skill by asking something like: whats my name?',
STOP: 'Bye! Thanks for using the Sample Alexa Customer Profile API Skill!',
};
const PERMISSIONS = ['alexa::profile:name:read', 'alexa::profile:email:read', 'alexa::profile:mobile_number:read'];
const LaunchRequest = {
canHandle(handlerInput) {
return handlerInput.requestEnvelope.request.type === 'LaunchRequest';
},
handle(handlerInput) {
return handlerInput.responseBuilder.speak(messages.WELCOME)
.reprompt(messages.WHAT_DO_YOU_WANT)
.getResponse();
},
};
const NameIntent = {
canHandle(handlerInput) {
const { request } = handlerInput.requestEnvelope;
return request.type === 'IntentRequest' && request.intent.name === 'NameIntent';
},
async handle(handlerInput) {
const { requestEnvelope, serviceClientFactory, responseBuilder } = handlerInput;
const consentToken = requestEnvelope.context.System.apiAccessToken;
if (!consentToken) {
return responseBuilder
.speak(messages.NOTIFY_MISSING_PERMISSIONS)
.withAskForPermissionsConsentCard(PERMISSIONS)
.getResponse();
}
try {
const client = serviceClientFactory.getUpsServiceClient();
const name = await client.getProfileName();
console.log('Name successfully retrieved, now responding to user.');
let response;
if (name == null) {
response = responseBuilder.speak(messages.NAME_MISSING).getResponse();
} else {
response = responseBuilder.speak(messages.NAME_AVAILABLE + name).getResponse();
}
return response;
} catch (error) {
if (error.name !== 'ServiceError') {
const response = responseBuilder.speak(messages.ERROR).getResponse();
return response;
}
throw error;
}
},
};
const EmailIntent = {
canHandle(handlerInput) {
const { request } = handlerInput.requestEnvelope;
return request.type === 'IntentRequest' && request.intent.name === 'EmailIntent';
},
async handle(handlerInput) {
const { requestEnvelope, serviceClientFactory, responseBuilder } = handlerInput;
const consentToken = requestEnvelope.context.System.apiAccessToken;
if (!consentToken) {
return responseBuilder
.speak(messages.NOTIFY_MISSING_PERMISSIONS)
.withAskForPermissionsConsentCard(PERMISSIONS)
.getResponse();
}
try {
const client = serviceClientFactory.getUpsServiceClient();
const email = await client.getProfileEmail();
console.log('Email successfully retrieved, now responding to user.');
let response;
if (email == null) {
response = responseBuilder.speak(messages.EMAIL_MISSING).getResponse();
} else {
response = responseBuilder.speak(messages.EMAIL_AVAILABLE + email).getResponse();
}
return response;
} catch (error) {
if (error.name !== 'ServiceError') {
const response = responseBuilder.speak(messages.ERROR).getResponse();
return response;
}
throw error;
}
},
};
const AddEmailIntentHandler = {
canHandle(handlerInput) {
return handlerInput.requestEnvelope.request.type === 'IntentRequest'
&& handlerInput.requestEnvelope.request.intent.name === 'AddEmailIntent';
},
async handle(handlerInput) {
const {responseBuilder } = handlerInput;
const userID = handlerInput.requestEnvelope.context.System.user.userId;
const client = serviceClientFactory.getUpsServiceClient();
const email = await client.getProfileEmail();
return dbHelper.addEmail(email, userID)
.then((data) => {
const speechText = `You have added the email id.`;
return responseBuilder
.speak(speechText)
.reprompt(GENERAL_REPROMPT)
.getResponse();
})
.catch((err) => {
console.log("Error occured while saving email", err);
const speechText = "we cannot save your email right now. Try again!"
return responseBuilder
.speak(speechText)
.getResponse();
})
},
};
const NumberIntent = {
canHandle(handlerInput) {
const { request } = handlerInput.requestEnvelope;
return request.type === 'IntentRequest' && request.intent.name === 'NumberIntent';
},
async handle(handlerInput) {
const { requestEnvelope, serviceClientFactory, responseBuilder } = handlerInput;
const consentToken = requestEnvelope.context.System.apiAccessToken;
if (!consentToken) {
return responseBuilder
.speak(messages.NOTIFY_MISSING_PERMISSIONS)
.withAskForPermissionsConsentCard(PERMISSIONS)
.getResponse();
}
try {
const client = serviceClientFactory.getUpsServiceClient();
const number = await client.getProfileMobileNumber();
console.log('Number successfully retrieved, now responding to user.');
let response;
if (number == null) {
response = responseBuilder.speak(messages.NUMBER_MISSING).getResponse();
} else {
response = responseBuilder.speak(`${messages.NUMBER_AVAILABLE} ${number.countryCode} ${number.phoneNumber}`).getResponse();
}
return response;
} catch (error) {
if (error.name !== 'ServiceError') {
const response = responseBuilder.speak(messages.ERROR).getResponse();
return response;
}
throw error;
}
},
};
const SessionEndedRequest = {
canHandle(handlerInput) {
return handlerInput.requestEnvelope.request.type === 'SessionEndedRequest';
},
handle(handlerInput) {
console.log(`Session ended with reason: ${handlerInput.requestEnvelope.request.reason}`);
return handlerInput.responseBuilder.getResponse();
},
};
const UnhandledIntent = {
canHandle() {
return true;
},
handle(handlerInput) {
return handlerInput.responseBuilder
.speak(messages.UNHANDLED)
.reprompt(messages.UNHANDLED)
.getResponse();
},
};
const HelpIntent = {
canHandle(handlerInput) {
const { request } = handlerInput.requestEnvelope;
return request.type === 'IntentRequest' && request.intent.name === 'AMAZON.HelpIntent';
},
handle(handlerInput) {
return handlerInput.responseBuilder
.speak(messages.HELP)
.reprompt(messages.HELP)
.getResponse();
},
};
const CancelIntent = {
canHandle(handlerInput) {
const { request } = handlerInput.requestEnvelope;
return request.type === 'IntentRequest' && request.intent.name === 'AMAZON.CancelIntent';
},
handle(handlerInput) {
return handlerInput.responseBuilder
.speak(messages.GOODBYE)
.getResponse();
},
};
const StopIntent = {
canHandle(handlerInput) {
const { request } = handlerInput.requestEnvelope;
return request.type === 'IntentRequest' && request.intent.name === 'AMAZON.StopIntent';
},
handle(handlerInput) {
return handlerInput.responseBuilder
.speak(messages.STOP)
.getResponse();
},
};
const ProfileError = {
canHandle(handlerInput, error) {
return error.name === 'ServiceError';
},
handle(handlerInput, error) {
if (error.statusCode === 403) {
return handlerInput.responseBuilder
.speak(messages.NOTIFY_MISSING_PERMISSIONS)
.withAskForPermissionsConsentCard(PERMISSIONS)
.getResponse();
}
return handlerInput.responseBuilder
.speak(messages.LOCATION_FAILURE)
.reprompt(messages.LOCATION_FAILURE)
.getResponse();
},
};
const skillBuilder = Alexa.SkillBuilders.standard();
exports.handler = skillBuilder
.addRequestHandlers(
LaunchRequest,
NameIntent,
EmailIntent,
AddEmailIntent,
NumberIntent,
SessionEndedRequest,
HelpIntent,
CancelIntent,
StopIntent,
UnhandledIntent,
)
.addErrorHandlers(ProfileError)
.withApiClient(new Alexa.DefaultApiClient())
.withCustomUserAgent('cookbook/customer-profile/v1')
.withTableName(dynamoDBTableName)
.withAutoCreateTable(true)
.lambda();