Skip to content

Commit f48257a

Browse files
authored
Merge pull request #14 from cybersource-tpi/master
Saved customer data wiped fix
2 parents 3eb6002 + 9eb314f commit f48257a

5 files changed

Lines changed: 117 additions & 33 deletions

File tree

src/index.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -397,7 +397,7 @@ app.post('/api/extension/payment/update', async (req, res) => {
397397
});
398398

399399
app.post('/api/extension/customer/update', async (req, res) => {
400-
let response: any;
400+
let response = paymentService.invalidInputResponse();
401401
let tokensToUpdate: any;
402402
let exceptionData: any;
403403
let microFormKeys: any;
@@ -440,7 +440,7 @@ app.post('/api/extension/customer/update', async (req, res) => {
440440
} else if ('update' == customFields.isv_tokenAction) {
441441
response = await paymentHandler.updateCardHandler(tokensToUpdate, customerObj.id, customerObj.obj);
442442
} else {
443-
response = paymentService.getUpdateTokenActions(customFields.isv_tokens, customFields.isv_failedTokens, true, customerObj, null);
443+
response = paymentService.getUpdateTokenActions(customFields.isv_tokens, customFields.isv_failedTokens, true, customerObj.obj, null);
444444
}
445445
}
446446
}
@@ -454,7 +454,7 @@ app.post('/api/extension/customer/update', async (req, res) => {
454454
}
455455
paymentService.logData(path.parse(path.basename(__filename)).name, Constants.POST_CUSTOMER_UPDATE, Constants.LOG_ERROR, null, exceptionData);
456456
}
457-
if (null == response) {
457+
if (null == response || undefined == response || (0 == response?.actions?.length && 0 == response?.errors?.length)) {
458458
requestObj = req.body.resource;
459459
if (null != requestObj && typeof requestObj === 'object') {
460460
customerObj = requestObj;

src/unit-tests/unit/PaymentService.spec.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ dotenv.config();
44
import paymentService from '../../utils/PaymentService';
55
import { fieldMapperFields, fieldMapperFieldObject, getOMServiceResponsePaymentResponse, getOMServiceResponsePaymentResponseObject, getOMServiceResponseTransactionDetail, visaCardDetailsActionVisaCheckoutData, getCapturedAmountRefundPaymentObj } from '../const/PaymentServiceConst';
66
import { getAuthResponsePaymentPendingResponse, getAuthResponsePaymentCompleteResponse, getAuthResponsePaymentResponse, getAuthResponsePaymentDeclinedResponse, getAuthResponsePaymentResponseObject, getAuthResponseTransactionDetail } from '../const/PaymentServiceConst';
7-
import { successState, failureState, changeStateTransactionDetail, changeStateFailureTransactionDetail, getRefundResponseUpdatePaymentObj, getRefundResponseUpdateTransactions } from '../const/PaymentServiceConst';
7+
import { successState, failureState, changeStateTransactionDetail, changeStateFailureTransactionDetail, getRefundResponseUpdatePaymentObj, getRefundResponseUpdateTransactions, deleteTokenCustomerObj } from '../const/PaymentServiceConst';
88
import { payerAuthActionsResponse, payerEnrollActionsUpdatePaymentObj, payerEnrollActionsResponse, addRefundActionAmount, addRefundActionOrderResponse, state } from '../const/PaymentServiceConst';
99
import { getUpdateTokenActionsActions, failurePaymentResponse, failureResponseTransactionDetail, getCreditCardResponseUpdatePaymentObj, getCreditCardResponseCartObj, clickToPayResponseUpdatePaymentObj } from '../const/PaymentServiceConst';
1010
import { getAuthorizedAmountCapturePaymentObj, setCustomTypeDataPendingAmount, setCustomTypeDataTransactionId, googlePayResponseUpdatePaymentObj, tokenCreateFlagCustomerInfo, tokenCreateFlagPaymentObj, tokenCreateFlagFunctionName } from '../const/PaymentServiceConst';
@@ -148,10 +148,14 @@ test.serial('Get payer enroll actions ', async (t) => {
148148
});
149149

150150
test.serial('Get update token actions ', async (t) => {
151-
const result = await paymentService.getUpdateTokenActions(getUpdateTokenActionsActions, null, true, null, null);
151+
const result = await paymentService.getUpdateTokenActions(getUpdateTokenActionsActions, null, true, deleteTokenCustomerObj, null);
152152
if (result) {
153-
t.is(result.actions[0].action, 'setCustomType');
154-
t.is(result.actions[0].type.key, 'isv_payments_customer_tokens');
153+
if(deleteTokenCustomerObj?.custom?.type?.id){
154+
t.is(result.actions[0].action, 'setCustomField');
155+
} else {
156+
t.is(result.actions[0].action, 'setCustomType');
157+
t.is(result.actions[0].type.key, 'isv_payments_customer_tokens');
158+
}
155159
} else {
156160
t.pass();
157161
}

src/utils/PaymentHandler.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -474,14 +474,14 @@ const addCardHandler = async (customerId, addressObj, customerObj) => {
474474
let cardTokens: any;
475475
let cardResponse: any;
476476
let customerTokenResponse: any;
477-
let existingTokens: any;
477+
let existingTokens: string[] = [];
478478
let existingTokensMap: any;
479479
let newToken: any;
480480
let parsedTokens: any;
481481
let tokenData: any;
482482
let exceptionData: any;
483483
let failedTokens: any;
484-
let existingFailedTokens: any;
484+
let existingFailedTokens: string [] = [];
485485
let existingFailedTokensMap: any;
486486
let paymentInstrumentId = null;
487487
let instrumentIdentifier = null;
@@ -629,8 +629,8 @@ const addCardHandler = async (customerId, addressObj, customerObj) => {
629629
} else {
630630
paymentService.logData(path.parse(path.basename(__filename)).name, Constants.FUNC_ADD_CARD_HANDLER, Constants.LOG_ERROR, Constants.LOG_CUSTOMER_ID + customerId, Constants.ERROR_MSG_INVALID_INPUT);
631631
}
632-
}
633-
632+
}
633+
634634
} catch (exception) {
635635
if (typeof exception === 'string') {
636636
exceptionData = Constants.EXCEPTION_MSG_ADDING_A_CARD + Constants.STRING_HYPHEN + exception.toUpperCase();

src/utils/PaymentService.ts

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -501,7 +501,7 @@ const payerEnrollActions = (response, updatePaymentObj) => {
501501

502502
const getUpdateTokenActions = (actions, existingFailedTokensMap, errorFlag, customerObj, address) => {
503503
let returnResponse: any;
504-
if (customerObj?.custom && customerObj.custom.fields?.isv_tokens) {
504+
if (customerObj?.custom?.type?.id) {
505505
returnResponse = {
506506
actions: [
507507
{
@@ -2187,6 +2187,7 @@ const setCustomerTokenData = async (cardTokens, paymentResponse, authResponse, e
21872187
let customerId = null;
21882188
let addressId = null;
21892189
let failedTokenLength = Constants.VAL_ZERO;
2190+
let customTypePresent = true;
21902191
if (null != cartObj && cartObj?.billingAddress?.id) {
21912192
addressId = cartObj.billingAddress.id;
21922193
}
@@ -2197,6 +2198,7 @@ const setCustomerTokenData = async (cardTokens, paymentResponse, authResponse, e
21972198
} else if (null != cartObj && updatePaymentObj?.custom?.fields?.isv_transientToken) {
21982199
customerInfo = await addTokenAddressForUC(updatePaymentObj, cartObj);
21992200
}
2201+
customTypePresent = (customerInfo?.custom?.type?.id) ? true : false;
22002202
if (customerInfo?.addresses && 0 < customerInfo.addresses.length ) {
22012203
addressId = customerInfo.addresses[customerInfo.addresses.length - 1].id;
22022204
}
@@ -2275,7 +2277,11 @@ const setCustomerTokenData = async (cardTokens, paymentResponse, authResponse, e
22752277
existingFailedTokensMap = [JSON.stringify(failedToken)];
22762278
}
22772279
}
2278-
customerTokenResponse = await commercetoolsApi.setCustomType(updatePaymentObj.customer.id, existingTokens, existingFailedTokensMap);
2280+
if (!customTypePresent) {
2281+
customerTokenResponse = await commercetoolsApi.setCustomType(updatePaymentObj.customer.id, existingTokens, existingFailedTokensMap);
2282+
} else {
2283+
customerTokenResponse = await commercetoolsApi.updateCustomerToken(existingTokens, customerInfo, existingFailedTokensMap);
2284+
}
22792285
if (null != customerTokenResponse) {
22802286
logData(path.parse(path.basename(__filename)).name, Constants.FUNC_SET_CUSTOMER_TOKEN_DATA, Constants.LOG_INFO, Constants.LOG_CUSTOMER_ID + updatePaymentObj.customer.id, Constants.SUCCESS_MSG_CARD_TOKENS_UPDATE);
22812287
} else {
@@ -2296,7 +2302,9 @@ const processTokens = async (customerTokenId, paymentInstrumentId, instrumentIde
22962302
let length = Constants.VAL_NEGATIVE_ONE;
22972303
let existingCardFlag = false;
22982304
let customerId = updatePaymentObj.customer.id;
2305+
let customTypePresent = true;
22992306
customerInfo = await commercetoolsApi.getCustomer(customerId);
2307+
customTypePresent = (customerInfo?.custom?.type?.id) ? true : false;
23002308
if (
23012309
null != customerInfo &&
23022310
Constants.STRING_CUSTOM in customerInfo &&
@@ -2323,7 +2331,11 @@ const processTokens = async (customerTokenId, paymentInstrumentId, instrumentIde
23232331
parsedTokens.cardExpiryYear = updatePaymentObj.custom.fields.isv_cardExpiryYear;
23242332
parsedTokens.addressId = addressId;
23252333
existingTokensMap[length] = JSON.stringify(parsedTokens);
2326-
updateTokenResponse = await commercetoolsApi.setCustomType(customerId, existingTokensMap, customerInfo.custom.fields.isv_failedTokens);
2334+
if (!customTypePresent) {
2335+
updateTokenResponse = await commercetoolsApi.setCustomType(customerId, existingTokensMap, customerInfo.custom.fields.isv_failedTokens);
2336+
} else {
2337+
updateTokenResponse = await commercetoolsApi.updateCustomerToken(existingTokensMap, customerInfo, customerInfo.custom.fields?.isv_failedTokens);
2338+
}
23272339
}
23282340
}
23292341
if (!existingCardFlag) {

src/utils/api/CommercetoolsApi.ts

Lines changed: 87 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -534,24 +534,26 @@ const updateCartByPaymentId = async (cartId, paymentId, cartVersion, visaCheckou
534534
};
535535

536536
const setCustomerTokens = async (tokenCustomerId, paymentInstrumentId, instrumentIdentifier, updatePaymentObj, addressId) => {
537-
let tokenResponse: any;
537+
let tokenResponse = null;
538538
let customerInfo: any;
539539
let client: any;
540540
let tokenData: any;
541541
let isvTokens: any;
542-
let mappedTokens: any;
542+
let mappedTokens: string[] = [];
543543
let exceptionData: any;
544-
let failedTokens: any;
544+
let failedTokens: string[] = [];
545545
let stringTokenData: string;
546546
let length: number;
547547
let tokenArray: Array<string>;
548548
let customerId = null;
549+
let customTypePresent = false;
549550
try {
550551
if (null != paymentInstrumentId && null != instrumentIdentifier && null != updatePaymentObj && Constants.STRING_CUSTOMER in updatePaymentObj && Constants.STRING_ID in updatePaymentObj.customer) {
551552
customerId = updatePaymentObj.customer.id;
552553
client = getClient();
553554
if (null != client && null != customerId) {
554555
customerInfo = await getCustomer(customerId);
556+
customTypePresent = (customerInfo?.custom?.type?.id) ? true : false;
555557
tokenData = {
556558
alias: updatePaymentObj.custom.fields.isv_tokenAlias,
557559
value: tokenCustomerId,
@@ -566,24 +568,27 @@ const setCustomerTokens = async (tokenCustomerId, paymentInstrumentId, instrumen
566568
timeStamp: new Date(Date.now()).toISOString(),
567569
};
568570
stringTokenData = JSON.stringify(tokenData);
569-
if (
570-
null != customerInfo &&
571-
Constants.STRING_CUSTOM in customerInfo &&
572-
Constants.STRING_FIELDS in customerInfo.custom &&
573-
Constants.ISV_TOKENS in customerInfo.custom.fields &&
574-
Constants.STRING_EMPTY != customerInfo.custom.fields.isv_tokens &&
575-
Constants.VAL_ZERO < customerInfo.custom.fields.isv_tokens.length
576-
) {
577-
failedTokens = customerInfo.custom.fields.isv_failedTokens;
578-
isvTokens = customerInfo.custom.fields.isv_tokens;
579-
mappedTokens = isvTokens.map((item) => item);
580-
length = mappedTokens.length;
581-
mappedTokens[length] = stringTokenData;
582-
tokenResponse = await setCustomType(customerId, mappedTokens, failedTokens);
583-
} else {
571+
if (customTypePresent) {
572+
if (
573+
null != customerInfo &&
574+
Constants.STRING_CUSTOM in customerInfo &&
575+
Constants.STRING_FIELDS in customerInfo.custom &&
576+
Constants.ISV_TOKENS in customerInfo.custom.fields &&
577+
Constants.STRING_EMPTY != customerInfo.custom.fields.isv_tokens &&
578+
Constants.VAL_ZERO < customerInfo.custom.fields.isv_tokens.length
579+
) {
580+
isvTokens = customerInfo.custom.fields.isv_tokens;
581+
mappedTokens = isvTokens.map((item) => item);
582+
length = mappedTokens.length;
583+
mappedTokens[length] = stringTokenData;
584+
} else {
585+
mappedTokens[0] = stringTokenData;
586+
}
584587
if (null != customerInfo && Constants.STRING_CUSTOM in customerInfo && Constants.STRING_FIELDS in customerInfo.custom) {
585588
failedTokens = customerInfo.custom.fields.isv_failedTokens;
586589
}
590+
tokenResponse = await updateCustomerToken(mappedTokens, customerInfo, failedTokens);
591+
} else {
587592
tokenArray = [stringTokenData];
588593
tokenResponse = await setCustomType(customerId, tokenArray, failedTokens);
589594
}
@@ -1274,6 +1279,68 @@ const addCustomerAddress = async (customerId, addressObj) => {
12741279
return customerResponse;
12751280
};
12761281

1282+
const updateCustomerToken = async (updateObject, customerObject, failedTokens) => {
1283+
let setCustomFieldResponse;
1284+
let actions = [] as any;
1285+
let exceptionData;
1286+
let customerId = '';
1287+
try {
1288+
if (customerObject) {
1289+
customerId = customerObject.id
1290+
const client = getClient();
1291+
if (null !== client) {
1292+
const requestBuilder = createRequestBuilder({
1293+
projectKey: process.env.CT_PROJECT_KEY,
1294+
});
1295+
const uri = requestBuilder.customers.byId(customerObject.id).build();
1296+
if (failedTokens) {
1297+
actions.push({
1298+
action: "setCustomField",
1299+
name: "isv_failedTokens",
1300+
value: failedTokens
1301+
});
1302+
}
1303+
if (updateObject) {
1304+
actions.push({
1305+
action: "setCustomField",
1306+
name: "isv_tokens",
1307+
value: updateObject
1308+
})
1309+
}
1310+
if(customerObject?.custom?.fields?.isv_tokenAction){
1311+
actions.push({
1312+
action: "setCustomField",
1313+
name: "isv_tokenAction",
1314+
value: null
1315+
})
1316+
}
1317+
const channelsRequest = {
1318+
uri: uri,
1319+
method: 'POST',
1320+
body: JSON.stringify({
1321+
version: customerObject.version,
1322+
actions: actions
1323+
})
1324+
};
1325+
setCustomFieldResponse = await client.execute(channelsRequest);
1326+
} else {
1327+
paymentService.logData(path.parse(path.basename(__filename)).name, 'FuncUpdateCustomerToken', Constants.LOG_INFO, '', Constants.ERROR_MSG_COMMERCETOOLS_CONNECT);
1328+
}
1329+
}
1330+
} catch (exception) {
1331+
if (typeof exception === 'string') {
1332+
exceptionData = Constants.EXCEPTION_MSG_CUSTOMER_UPDATE + Constants.STRING_HYPHEN + exception.toUpperCase();
1333+
} else if (exception instanceof Error) {
1334+
exceptionData = Constants.EXCEPTION_MSG_CUSTOMER_UPDATE + Constants.STRING_HYPHEN + exception.message;
1335+
} else {
1336+
exceptionData = Constants.EXCEPTION_MSG_CUSTOMER_UPDATE + Constants.STRING_HYPHEN + exception;
1337+
}
1338+
paymentService.logData(path.parse(path.basename(__filename)).name, 'FuncUpdateCustomerTokens', Constants.LOG_ERROR, 'CustomerId : ' + customerId, exceptionData);
1339+
setCustomFieldResponse = exception;
1340+
}
1341+
return setCustomFieldResponse;
1342+
}
1343+
12771344

12781345

12791346
export default {
@@ -1299,5 +1366,6 @@ export default {
12991366
addCustomField,
13001367
updateAvailableAmount,
13011368
getCartById,
1302-
addCustomerAddress
1369+
addCustomerAddress,
1370+
updateCustomerToken
13031371
};

0 commit comments

Comments
 (0)