示例 Node.JS 代码中 createCustomerProfile 的异步问题
Asynchronous Issue with createCustomerProfile in Sample Node.JS code
我们的目标是使用 Node SDK 示例代码将 Authorize.NET 集成到我们的应用程序中。
节点SDK:https://github.com/AuthorizeNet/sdk-node
推荐示例代码:https://github.com/AuthorizeNet/sample-code-node/tree/ef9e5c2d9e0379b5f47a0ebcb6847e711fe196ef
我正在尝试创建客户付款资料,虽然我能够成功创建客户资料并收到来自 API 电话的成功响应
CustomerProfilesModule.createCustomerProfile,我的 auth.controller.js 的剩余部分在我得到 API 结果之前运行。所有 create-customer-profile.js 一直运行到 ctrl.execute() 运行,然后 auth.controller.js 中的 console.log("xxx") 在抓取 [=38 之前运行=] 结果。
我知道这是我的代码的同步问题,但我不知道如何解决。我正在使用提供的示例代码 authorize.NET,但是该代码使用的是来自我的应用程序的真实数据,而不是示例数据。我非常乐意根据要求提供更多信息,非常感谢任何帮助!
// AUTH.CONTROLLER.JS
const httpStatus = require("http-status");
const ApiContracts = require("authorizenet").APIContracts;
const ApiControllers = require("authorizenet").APIControllers;
const SDKConstants = require("authorizenet").Constants;
const User = require("../models/user.model");
const RefreshToken = require("../models/refreshToken.model");
const moment = require("moment-timezone");
const { jwtExpirationInterval } = require("../../config/vars");
const sgMail = require("@sendgrid/mail");
const bcrypt = require("bcryptjs");
const CustomerProfilesModule = require("../utils/authorizeNet/CustomerProfiles");
sgMail.setApiKey(process.env.SENDGRID_API_KEY.replace(/\r?\n|\r/g, ""));
exports.register = async (req, res, next) => {
try {
const userData = req.body;
let customerProfileResult =
await CustomerProfilesModule.createCustomerProfile(userData);
console.log(
"❌ ❌ ❌ ❌ ❌ customerProfile Result ",
customerProfileResult
);
if (!userData || userData.error) {
return next(error);
} else {
const { isTrial } = userData;
const user = await new User(userData).save();
const token = generateTokenResponse(user, user.token());
res.status(httpStatus.CREATED);
return res.json({ token, user });
}
} catch (error) {
console.log(error.message);
return next(User.checkDuplicateEmail(error));
}
};
//////////
// CREATE-CUSTOMER-PROFILE.JS
var ApiContracts = require("authorizenet").APIContracts;
var ApiControllers = require("authorizenet").APIControllers;
var utils = require("../utils.js");
async function createCustomerProfile(user) {
console.log(" user parameter", user);
var merchantAuthenticationType =
new ApiContracts.MerchantAuthenticationType();
merchantAuthenticationType.setName(process.env.AUTHORIZE_NET_API_LOGIN_KEY);
merchantAuthenticationType.setTransactionKey(
process.env.AUTHORIZE_NET_TRANSACTION_KEY
);
var creditCard = new ApiContracts.CreditCardType();
creditCard.setCardNumber(user.cardNumber);
if (user.cardExpiry.length > 4) {
creditCard.setExpirationDate(
`${user.cardExpiry.slice(0, 1)}${user.cardExpiry.slice(3, 4)}`
);
} else {
creditCard.setExpirationDate(user.cardExpiry);
}
console.log("creditCard", creditCard);
var paymentType = new ApiContracts.PaymentType();
paymentType.setCreditCard(creditCard);
var customerAddress = new ApiContracts.CustomerAddressType();
customerAddress.setFirstName(user.firstName);
customerAddress.setLastName(user.lastName);
customerAddress.setAddress(user.mailingAddress);
customerAddress.setCity(user.mailingCity);
customerAddress.setState(user.mailingState);
customerAddress.setZip(user.mailingZip);
customerAddress.setCountry("USA");
customerAddress.setPhoneNumber(user.userPhone);
var customerPaymentProfileType =
new ApiContracts.CustomerPaymentProfileType();
customerPaymentProfileType.setCustomerType(
ApiContracts.CustomerTypeEnum.INDIVIDUAL
);
customerPaymentProfileType.setPayment(paymentType);
customerPaymentProfileType.setBillTo(customerAddress);
var paymentProfilesList = [];
paymentProfilesList.push(customerPaymentProfileType);
console.log(
"paymentProfilesList",
paymentProfilesList
);
var customerProfileType = new ApiContracts.CustomerProfileType();
customerProfileType.setMerchantCustomerId(
"M_" + utils.getRandomString("cust")
);
customerProfileType.setDescription(
`${user.firstName} ${user.lastName}'s Account'`
);
customerProfileType.setEmail(user.userEmail);
customerProfileType.setPaymentProfiles(paymentProfilesList);
var createRequest = new ApiContracts.CreateCustomerProfileRequest();
createRequest.setProfile(customerProfileType);
createRequest.setValidationMode(ApiContracts.ValidationModeEnum.TESTMODE);
createRequest.setMerchantAuthentication(merchantAuthenticationType);
var ctrl = new ApiControllers.CreateCustomerProfileController(
createRequest.getJSON()
);
// All above code is ran when CustomerProfilesModule.createCustomerProfile(userData) is executed in auth.controller.js
// However the following line (line 130 in auth.controller.js) is ran before the below ctrl.execute() code is completed
//
// console.log("❌ ❌ ❌ ❌ ❌ customerProfile Result ", customerProfileResult);
//
// All the above code is executed before that console.log("❌ ❌ ❌") statement above, however the below code doesn't run before that console.log
// I'd like the below code to execute before the remaining register route is finished, but just don't know what is going on!
ctrl.execute(async function () {
var apiResponse = await ctrl.getResponse();
console.log("apiResponse", apiResponse);
var response = new ApiContracts.CreateCustomerProfileResponse(apiResponse);
console.log("response", response);
//pretty print response
//console.log(JSON.stringify(response, null, 2));
if (response != null) {
if (
response.getMessages().getResultCode() ==
ApiContracts.MessageTypeEnum.OK
) {
console.log(
"Successfully created a customer profile with id: " +
response.getCustomerProfileId()
);
} else {
console.log("Result Code: " + response.getMessages().getResultCode());
console.log(
"Error Code: " + response.getMessages().getMessage()[0].getCode()
);
console.log(
"Error message: " + response.getMessages().getMessage()[0].getText()
);
return {
error:
"Error message: " +
response.getMessages().getMessage()[0].getText(),
};
}
} else {
console.log("Null response received");
return { error: "Null response received" };
}
});
}
module.exports.createCustomerProfile = createCustomerProfile;
我对您的代码的理解还不够充分,无法知道您希望它如何工作。但是根据我的理解,console.log
在你接到 api 的电话和你接到 api 之间的 运行ning 之间,使它处于一个尴尬的阶段。
异步代码的工作原理是 JavaScript 让异步函数 运行 离开,同时做一些其他事情,完成后返回。
我在您的代码中看到的问题是 createCustomerProfile
在完成后 return 什么也没有。您有一个 return 承诺无效的函数。首先,这是一个问题,因为您在 console.log()
.
中使用函数的 return 值
我强烈建议 promisify 以便它正确解决或出现错误,当您使用 API 时,您可能会遇到您想要处理的潜在错误。
你说 console.log()
在 ctrl.execute()
之前被调用,但我根本看不到它在哪里执行,因为我在 createCustomerProfile
中没有看到它函数。
ctrl.execute 是一种处理未调用的 IIFE 函数的方法。
IIFE 函数在定义后立即调用。
您将无法在申报前运行 IIFE。
可能的解决方案:
尝试在 register 路由中创建一个回调路由,然后在实际路由完成之前排除 IIFE 以从 register 中的回调中获取响应。
我们的目标是使用 Node SDK 示例代码将 Authorize.NET 集成到我们的应用程序中。
节点SDK:https://github.com/AuthorizeNet/sdk-node
推荐示例代码:https://github.com/AuthorizeNet/sample-code-node/tree/ef9e5c2d9e0379b5f47a0ebcb6847e711fe196ef
我正在尝试创建客户付款资料,虽然我能够成功创建客户资料并收到来自 API 电话的成功响应 CustomerProfilesModule.createCustomerProfile,我的 auth.controller.js 的剩余部分在我得到 API 结果之前运行。所有 create-customer-profile.js 一直运行到 ctrl.execute() 运行,然后 auth.controller.js 中的 console.log("xxx") 在抓取 [=38 之前运行=] 结果。
我知道这是我的代码的同步问题,但我不知道如何解决。我正在使用提供的示例代码 authorize.NET,但是该代码使用的是来自我的应用程序的真实数据,而不是示例数据。我非常乐意根据要求提供更多信息,非常感谢任何帮助!
// AUTH.CONTROLLER.JS
const httpStatus = require("http-status");
const ApiContracts = require("authorizenet").APIContracts;
const ApiControllers = require("authorizenet").APIControllers;
const SDKConstants = require("authorizenet").Constants;
const User = require("../models/user.model");
const RefreshToken = require("../models/refreshToken.model");
const moment = require("moment-timezone");
const { jwtExpirationInterval } = require("../../config/vars");
const sgMail = require("@sendgrid/mail");
const bcrypt = require("bcryptjs");
const CustomerProfilesModule = require("../utils/authorizeNet/CustomerProfiles");
sgMail.setApiKey(process.env.SENDGRID_API_KEY.replace(/\r?\n|\r/g, ""));
exports.register = async (req, res, next) => {
try {
const userData = req.body;
let customerProfileResult =
await CustomerProfilesModule.createCustomerProfile(userData);
console.log(
"❌ ❌ ❌ ❌ ❌ customerProfile Result ",
customerProfileResult
);
if (!userData || userData.error) {
return next(error);
} else {
const { isTrial } = userData;
const user = await new User(userData).save();
const token = generateTokenResponse(user, user.token());
res.status(httpStatus.CREATED);
return res.json({ token, user });
}
} catch (error) {
console.log(error.message);
return next(User.checkDuplicateEmail(error));
}
};
//////////
// CREATE-CUSTOMER-PROFILE.JS
var ApiContracts = require("authorizenet").APIContracts;
var ApiControllers = require("authorizenet").APIControllers;
var utils = require("../utils.js");
async function createCustomerProfile(user) {
console.log(" user parameter", user);
var merchantAuthenticationType =
new ApiContracts.MerchantAuthenticationType();
merchantAuthenticationType.setName(process.env.AUTHORIZE_NET_API_LOGIN_KEY);
merchantAuthenticationType.setTransactionKey(
process.env.AUTHORIZE_NET_TRANSACTION_KEY
);
var creditCard = new ApiContracts.CreditCardType();
creditCard.setCardNumber(user.cardNumber);
if (user.cardExpiry.length > 4) {
creditCard.setExpirationDate(
`${user.cardExpiry.slice(0, 1)}${user.cardExpiry.slice(3, 4)}`
);
} else {
creditCard.setExpirationDate(user.cardExpiry);
}
console.log("creditCard", creditCard);
var paymentType = new ApiContracts.PaymentType();
paymentType.setCreditCard(creditCard);
var customerAddress = new ApiContracts.CustomerAddressType();
customerAddress.setFirstName(user.firstName);
customerAddress.setLastName(user.lastName);
customerAddress.setAddress(user.mailingAddress);
customerAddress.setCity(user.mailingCity);
customerAddress.setState(user.mailingState);
customerAddress.setZip(user.mailingZip);
customerAddress.setCountry("USA");
customerAddress.setPhoneNumber(user.userPhone);
var customerPaymentProfileType =
new ApiContracts.CustomerPaymentProfileType();
customerPaymentProfileType.setCustomerType(
ApiContracts.CustomerTypeEnum.INDIVIDUAL
);
customerPaymentProfileType.setPayment(paymentType);
customerPaymentProfileType.setBillTo(customerAddress);
var paymentProfilesList = [];
paymentProfilesList.push(customerPaymentProfileType);
console.log(
"paymentProfilesList",
paymentProfilesList
);
var customerProfileType = new ApiContracts.CustomerProfileType();
customerProfileType.setMerchantCustomerId(
"M_" + utils.getRandomString("cust")
);
customerProfileType.setDescription(
`${user.firstName} ${user.lastName}'s Account'`
);
customerProfileType.setEmail(user.userEmail);
customerProfileType.setPaymentProfiles(paymentProfilesList);
var createRequest = new ApiContracts.CreateCustomerProfileRequest();
createRequest.setProfile(customerProfileType);
createRequest.setValidationMode(ApiContracts.ValidationModeEnum.TESTMODE);
createRequest.setMerchantAuthentication(merchantAuthenticationType);
var ctrl = new ApiControllers.CreateCustomerProfileController(
createRequest.getJSON()
);
// All above code is ran when CustomerProfilesModule.createCustomerProfile(userData) is executed in auth.controller.js
// However the following line (line 130 in auth.controller.js) is ran before the below ctrl.execute() code is completed
//
// console.log("❌ ❌ ❌ ❌ ❌ customerProfile Result ", customerProfileResult);
//
// All the above code is executed before that console.log("❌ ❌ ❌") statement above, however the below code doesn't run before that console.log
// I'd like the below code to execute before the remaining register route is finished, but just don't know what is going on!
ctrl.execute(async function () {
var apiResponse = await ctrl.getResponse();
console.log("apiResponse", apiResponse);
var response = new ApiContracts.CreateCustomerProfileResponse(apiResponse);
console.log("response", response);
//pretty print response
//console.log(JSON.stringify(response, null, 2));
if (response != null) {
if (
response.getMessages().getResultCode() ==
ApiContracts.MessageTypeEnum.OK
) {
console.log(
"Successfully created a customer profile with id: " +
response.getCustomerProfileId()
);
} else {
console.log("Result Code: " + response.getMessages().getResultCode());
console.log(
"Error Code: " + response.getMessages().getMessage()[0].getCode()
);
console.log(
"Error message: " + response.getMessages().getMessage()[0].getText()
);
return {
error:
"Error message: " +
response.getMessages().getMessage()[0].getText(),
};
}
} else {
console.log("Null response received");
return { error: "Null response received" };
}
});
}
module.exports.createCustomerProfile = createCustomerProfile;
我对您的代码的理解还不够充分,无法知道您希望它如何工作。但是根据我的理解,console.log
在你接到 api 的电话和你接到 api 之间的 运行ning 之间,使它处于一个尴尬的阶段。
异步代码的工作原理是 JavaScript 让异步函数 运行 离开,同时做一些其他事情,完成后返回。
我在您的代码中看到的问题是 createCustomerProfile
在完成后 return 什么也没有。您有一个 return 承诺无效的函数。首先,这是一个问题,因为您在 console.log()
.
我强烈建议 promisify 以便它正确解决或出现错误,当您使用 API 时,您可能会遇到您想要处理的潜在错误。
你说 console.log()
在 ctrl.execute()
之前被调用,但我根本看不到它在哪里执行,因为我在 createCustomerProfile
中没有看到它函数。
ctrl.execute 是一种处理未调用的 IIFE 函数的方法。 IIFE 函数在定义后立即调用。
您将无法在申报前运行 IIFE。
可能的解决方案:
尝试在 register 路由中创建一个回调路由,然后在实际路由完成之前排除 IIFE 以从 register 中的回调中获取响应。