Я использую AWS Amplify для аутентификации и Stripe для оплаты создания страницы регистрации.
ПРОБЛЕМА: Я не могу найти способ объединить проверки для раздела электронной почты и пароля (из AWS Amplify) с разделом информации о платеже (из Stripe).
Мой текущий код создает токен Stripe и вызывает API (с действительной информацией о платеже), а затем обрабатывает сообщение об ошибке от userSignupRequest, которое заботится о полях электронной почты и пароля.
Как мне подтвердить адрес электронной почты и пароль с платежной информацией, а затем создать учетную запись в AWS и Stripe?
// Stripe payment process
this.props.stripe.createToken(
{
email: this.state.email
}
).then(result => {
// PROBLEM: Form server validation from Stripe
if (result.error){
return this.setState({ errors: { errorMsg: result.error.message }, isLoading: false })
}
// if success, create customer and subscription with result.token.id
const apiName = 'NameOfAPI';
const path = '/stripe/signup';
let myInit = {
body: {
"stripeToken": result.token.id,
"email": this.state.email
}
}
API.post(apiName , path, myInit).then(reponse => {
this.props.userSignupRequest(this.state.email, this.state.password, reponse).then(user => {
this.setState({
confirmAccount: true,
isLoading: false,
userEmail: this.state.email,
errors: {}
})
this.props.history.push('/signup#confirm-account')
}).catch(err => {
// PROBLEM: Form server validation
this.setState({ errors: { errorMsg: err.message }, isLoading: false })
})
}).catch(err => {
console.info(err)
this.setState({ errors: { errorMsg: err }, isLoading: false })
});
})
Я использую API расширения AWS, который использует Lambda с узлом 6.10



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Похоже, у нас очень похожий стек. Мое решение заключалось в том, чтобы обрабатывать все на стороне сервера. Вам необходимо предоставить лямбда-функциям соответствующие разрешения IAM для доступа к Cognito. Код ниже немного длинный. Я использую асинхронный / ожидание, который действительно меняет порядок. Однако вам нужно будет использовать Lambda с узлом 8, чтобы использовать async / await.
Я подтверждаю, что все соответствует правильному формату на стороне клиента (т.е. электронные письма действительно являются электронными письмами, а пароли имеют правильную длину). Я понял, что единственная ошибка, которая может возникнуть, - это ошибка «существующий пользователь» от Cognito. Идея такова: проверьте, существует ли пользователь, прежде чем пытаться подписать его с помощью Stripe. Невозможно «проверить», действительна ли кредитная карта пользователя в Stripe. Все или ничего. Если он действителен, он пройдет, если нет, вы получите сообщение об ошибке. Если это произойдет, вы можете зарегистрировать пользователя с помощью Cognito, зная, что вы не должны получать ошибку (вы проверили адрес электронной почты и пароль на стороне клиента и знаете, что использование еще не существует).
Для справки вот aws-sdk для когнито.
const AWS = require('aws-sdk');
const cognito = new AWS.CognitoIdentityServiceProvider({
region: "region",
userPoolId: "cognito_user_pool_id",
});
module.exports.signUpUser = (payload) => {
const usernamePayload = {
UserPoolId: "cognito_user_pool_id",
Username: payload.email,
};
// I use emails for usernames.
new Promise((resolve, reject) => {
cognito.adminGetUser(usernamePayload, (error, response) => {
if (error && error.code === 'UserNotFoundException') {
resolve(false);
} else if (error) {
reject(error);
} else {
// if adminGetUser doesn't fail, it means the username exists
resolve(true);
}
});
}).then((usernameExists) => {
if (!usernameExists) {
// run stripe API stuff
// always run before sign up below to catch stripe errors
// and return those errors to client
// before you sign up the user to Cognito
// since you've already verified the user does not exist
// it would be rare for an error to come up here
// as long as you validate passwords and emails client-side
const signUpPayload = {
ClientId: "cognito_user_pool_client_id",
Username: payload.email,
Password: payload.password,
UserAttributes: [
{
Name: 'email',
Value: payload.email,
},
],
};
new Promise((resolve, reject) => {
cognito.signUp(signUpPayload, (error, response) => {
if (error) {
reject(error);
} else {
resolve(response);
}
});
}).catch((error) => {
// you should hopefully encounter no errors here
// once you get everything setup correctly
console.info(error);
})
} else {
// means username already exists, send error to client
// saying username exists
}
}).catch((error) => {
// may want to dispatch this error to client
console.info(error);
});
return null;
};
Я использую мобильный хаб AWS для аутентификации. Как выглядит установка lambda functions the appropriate IAM permissions to access Cognito?
Для вас это может быть слишком большим изменением. AWS mobile обрабатывает все ваши данные о пользовательском пуле когнитивных технологий. Этот метод потребует, чтобы вы начали обрабатывать некоторые из них. Вам нужно будет получить как минимум свой «идентификатор пула пользователей» и, возможно, создать клиент приложения в своем пуле пользователей, чтобы получить «идентификатор клиента». Кроме того, вам нужно будет создать роль IAM для функций Lambda и прикрепить к ней разрешение, открывающее доступ к Cognito. Затем вам нужно будет добавить эту роль в вашу лямбда-функцию. Если вы посмотрите на одну из ваших лямбда-функций, там должна быть область, где вы можете добавить роль IAM.
По сути, это единственная настройка, которую я мог придумать, чтобы предотвратить добавление пользователей в Cognito, а затем их отклонение из Stripe (потому что их кредитная карта неправильная и т. д.) Или наоборот (взимается по полосе, но тогда их адрес электронной почты уже существует - поэтому они не могут создать новую учетную запись когнито, и теперь их адрес электронной почты неверен).
Было бы хорошо дать вам серверное решение? Если да, то используете ли вы node, и если да, то какой версии? Я думаю, что ваше решение - лучшее решение на стороне клиента.