如何处理承诺链中的多个错误?
How to handle multiple errors in promise chain?
我使用 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.log(err)
this.setState({ errors: { errorMsg: err }, isLoading: false })
});
})
看来我们的堆栈非常相似。我的解决方案是在服务器端处理所有事情。您需要为您的 lambda 函数授予访问 Cognito 的适当 IAM 权限。下面的代码有点长。我使用 async/await,它确实为我清理了一切。不过,您需要将 Lambda 与节点 8 一起使用才能使用 async/await。
我验证所有内容都与客户端的正确格式匹配(即电子邮件确实是电子邮件,密码长度正确)。我意识到唯一可能出现的错误是来自 Cognito 的 "existing user" 错误。这个想法是:在尝试用 Stripe 注册用户之前测试用户是否存在。如果用户的信用卡对 Stripe 有效,则无法 "test"。全有或全无。如果有效,它将通过,否则,您将收到错误消息。如果成功,您就可以使用 Cognito 注册用户,知道您不应该收到错误(您已经在客户端验证了电子邮件和密码,并且您知道该用途尚不存在)。
供参考,这里是 aws-sdk for cognito。
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.log(error);
})
} else {
// means username already exists, send error to client
// saying username exists
}
}).catch((error) => {
// may want to dispatch this error to client
console.log(error);
});
return null;
};
我使用 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.log(err)
this.setState({ errors: { errorMsg: err }, isLoading: false })
});
})
看来我们的堆栈非常相似。我的解决方案是在服务器端处理所有事情。您需要为您的 lambda 函数授予访问 Cognito 的适当 IAM 权限。下面的代码有点长。我使用 async/await,它确实为我清理了一切。不过,您需要将 Lambda 与节点 8 一起使用才能使用 async/await。
我验证所有内容都与客户端的正确格式匹配(即电子邮件确实是电子邮件,密码长度正确)。我意识到唯一可能出现的错误是来自 Cognito 的 "existing user" 错误。这个想法是:在尝试用 Stripe 注册用户之前测试用户是否存在。如果用户的信用卡对 Stripe 有效,则无法 "test"。全有或全无。如果有效,它将通过,否则,您将收到错误消息。如果成功,您就可以使用 Cognito 注册用户,知道您不应该收到错误(您已经在客户端验证了电子邮件和密码,并且您知道该用途尚不存在)。
供参考,这里是 aws-sdk for cognito。
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.log(error);
})
} else {
// means username already exists, send error to client
// saying username exists
}
}).catch((error) => {
// may want to dispatch this error to client
console.log(error);
});
return null;
};