From 91af24c3dbca66ae296f3b2fdd9211ff575aa6ee Mon Sep 17 00:00:00 2001 From: Felipe Polo-Wood Date: Tue, 4 Apr 2017 07:58:50 -0400 Subject: [PATCH 01/12] Pass Gateway response if Issuer response is empty --- lib/infrastructure/helpers.js | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/lib/infrastructure/helpers.js b/lib/infrastructure/helpers.js index 8311625..c74e418 100644 --- a/lib/infrastructure/helpers.js +++ b/lib/infrastructure/helpers.js @@ -12,6 +12,23 @@ function defNn(v) { return v !== undefined && v !== null; }; +function isEmptyObject(o){ + if (o === null){ + return true; + } + if (o.length===0){ + return true; + } + if (JSON.stringify(o)==="{}"){ + return true; + } + if (typeof(o)!=='object'){ + return true; + } + return false; +} + + var Helpers = { isNumeric: isNumeric, @@ -20,6 +37,8 @@ var Helpers = { defNn: defNn, + isEmptyObject: isEmptyObject, + hydrateCardData: function hydrateCardData(obj) { var result = {}; From d8d438b2e36b0c3640397629e6467e877b1b6dd5 Mon Sep 17 00:00:00 2001 From: Felipe Polo-Wood Date: Tue, 4 Apr 2017 07:59:20 -0400 Subject: [PATCH 02/12] Pass Gateway response if Issuer response is empty --- test/portico-services/helpers-test.js | 31 +++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 test/portico-services/helpers-test.js diff --git a/test/portico-services/helpers-test.js b/test/portico-services/helpers-test.js new file mode 100644 index 0000000..3d7e2d9 --- /dev/null +++ b/test/portico-services/helpers-test.js @@ -0,0 +1,31 @@ +'use strict'; + +var assert = require('assert'), + helpers = require('../../lib/infrastructure/helpers'); + +exports.isEmptyObject = { + onNull: function () { + var rc = helpers.isEmptyObject(null); + assert.equal(rc,true,'null should return true'); + }, + + onEmpty: function(){ + var rc = helpers.isEmptyObject({}); + assert.equal(rc,true,'{} should return true'); + }, + + onNotObject: function() { + var rc = helpers.isEmptyObject(''); + assert.equal(rc,true,'\'\' should return true'); + }, + + onString: function(){ + var rc = helpers.isEmptyObject(' '); + assert.equal(rc,true,'\' \' should return true'); + }, + + onNotEmpty: function(){ + var rc = helpers.isEmptyObject({x:0}); + assert.equal(rc,false,'{x:0} should return false'); + } +}; From 10b05a7e936e12717ddd6e968945eea64db5c1aa Mon Sep 17 00:00:00 2001 From: Felipe Polo-Wood Date: Tue, 4 Apr 2017 08:04:42 -0400 Subject: [PATCH 03/12] Pass Gateway response if Issuer response is empty --- lib/services/secure-submit/hps-credit-service.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/services/secure-submit/hps-credit-service.js b/lib/services/secure-submit/hps-credit-service.js index c2efd1c..4746f1d 100644 --- a/lib/services/secure-submit/hps-credit-service.js +++ b/lib/services/secure-submit/hps-credit-service.js @@ -859,8 +859,8 @@ function HpsCreditService(hpsConfig, soapUri) { transactionId: t.GatewayTxnId, originalTransactionId: t.OriginalGatewayTxnId, maskedCardNumber: t.MaskedCardNbr, - responseCode: t.IssuerRspCode, - responseText: t.IssuerRspText, + responseCode: isEmptyObject(t.IssuerRspCode)?(isEmptyObject(t.GatewayRspCode)?'':t.GatewayRspCode):t.IssuerRspCode, + responseText: isEmptyObject(t.IssuerRspText)?(isEmptyObject(t.GatewayRspMsg)?'':t.GatewayRspMsg):t.IssuerRspText, amount: t.Amt, settlementAmount: t.SettlementAmt, transactionUtcDate: t.TxnUtcDT, From 37f4722640c4ce76e17d401e070825126dddb42f Mon Sep 17 00:00:00 2001 From: Felipe Polo-Wood Date: Tue, 4 Apr 2017 11:25:11 -0400 Subject: [PATCH 04/12] Fix typo on helpers --- lib/infrastructure/helpers.js | 2 +- test/portico-services/helpers-test.js | 51 +++++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 1 deletion(-) diff --git a/lib/infrastructure/helpers.js b/lib/infrastructure/helpers.js index c74e418..7331c9c 100644 --- a/lib/infrastructure/helpers.js +++ b/lib/infrastructure/helpers.js @@ -113,7 +113,7 @@ var Helpers = { return 'Refund'; case 'CreditReversal': return 'Reverse'; - case 'creditAuth': + case 'CreditAuth': return 'Authorize'; case 'CreditAccountVerify': return 'Verify'; diff --git a/test/portico-services/helpers-test.js b/test/portico-services/helpers-test.js index 3d7e2d9..4c61988 100644 --- a/test/portico-services/helpers-test.js +++ b/test/portico-services/helpers-test.js @@ -1,6 +1,7 @@ 'use strict'; var assert = require('assert'), + schema = require('../../lib/infrastructure/validation/portico-schema'), helpers = require('../../lib/infrastructure/helpers'); exports.isEmptyObject = { @@ -29,3 +30,53 @@ exports.isEmptyObject = { assert.equal(rc,false,'{x:0} should return false'); } }; + +exports.validateRequestTypes = { + validObjects: function(){ + requestTypes.map(rt=>{ + var rc = schema.requestType(rt); + assert.equal(helpers.isEmptyObject(rc),false, rt + ' should be a valid type'); + }); + }, + validTransactions: function(){ + requestTypes.map(rt=>{ + var rc = helpers.serviceNameToTransactionType(rt); + assert.notEqual(rc,null, rt + ' should have a Transaction Type'); + }); + }, + + validServiceNames: function(){ + requestTypes.map(rt=>{ + var rc = helpers.serviceNameToTransactionType(rt); + var rc2 = helpers.transactionTypeToServiceName(rc); + assert.notEqual(rc,null,rt + ' should be a valid Service Name'); + assert.equal(rt,rc2, rt + ' should be the same as ' + rc2); + }); + } +}; + +function isRequestObject(o){ + var rc = false; + if (!helpers.isEmptyObject(o)){ + if (o.type==='object'&&!isEmptyObject(o.properties)){ + rc = true; + } + } + return rc; +} + +var requestTypes = [ + 'CreditSale', + 'CreditAuth', + 'CreditAccountVerify', + 'CreditAddToBatch', + 'CreditReturn', + 'CreditReversal', + 'ReportActivity', + //'ReportBatchDetail', + //'ReportBatchHistory', + //'ReportBatchSummary', + //'ReportOpenAuths', + 'ReportTxnDetail', + 'ManageTokens' +] \ No newline at end of file From b472f51ba3d8908d7ba3c324700ed77d8217cc79 Mon Sep 17 00:00:00 2001 From: Felipe Polo-Wood Date: Tue, 4 Apr 2017 13:07:39 -0400 Subject: [PATCH 05/12] Added more Transaction types and Services --- lib/infrastructure/helpers.js | 12 ++++++++++++ lib/services/secure-submit/hps-credit-service.js | 4 ++-- test/portico-services/helpers-test.js | 6 +++--- 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/lib/infrastructure/helpers.js b/lib/infrastructure/helpers.js index 7331c9c..2499999 100644 --- a/lib/infrastructure/helpers.js +++ b/lib/infrastructure/helpers.js @@ -129,6 +129,12 @@ var Helpers = { return 'ManageTokens'; case 'SecurityError': return 'SecurityError'; + case 'ReportBatchDetail': + return 'BatchDetail'; + case 'ReportBatchHistory': + return 'BatchHistory'; + case 'ReportBatchSummary': + return 'BatchSummary'; default: return null; } @@ -161,6 +167,12 @@ var Helpers = { return 'BatchClose'; case 'SecurityError': return "SecurityError"; + case 'BatchDetail': + return 'ReportBatchDetail'; + case 'BatchHistory': + return 'ReportBatchHistory'; + case 'BatchSummary': + return 'ReportBatchSummary'; default: return ''; } diff --git a/lib/services/secure-submit/hps-credit-service.js b/lib/services/secure-submit/hps-credit-service.js index 4746f1d..6fb4830 100644 --- a/lib/services/secure-submit/hps-credit-service.js +++ b/lib/services/secure-submit/hps-credit-service.js @@ -859,8 +859,8 @@ function HpsCreditService(hpsConfig, soapUri) { transactionId: t.GatewayTxnId, originalTransactionId: t.OriginalGatewayTxnId, maskedCardNumber: t.MaskedCardNbr, - responseCode: isEmptyObject(t.IssuerRspCode)?(isEmptyObject(t.GatewayRspCode)?'':t.GatewayRspCode):t.IssuerRspCode, - responseText: isEmptyObject(t.IssuerRspText)?(isEmptyObject(t.GatewayRspMsg)?'':t.GatewayRspMsg):t.IssuerRspText, + responseCode: hlp.isEmptyObject(t.IssuerRspCode)?(hlp.isEmptyObject(t.GatewayRspCode)?'':t.GatewayRspCode):t.IssuerRspCode, + responseText: hlp.isEmptyObject(t.IssuerRspText)?(hlp.isEmptyObject(t.GatewayRspMsg)?'':t.GatewayRspMsg):t.IssuerRspText, amount: t.Amt, settlementAmount: t.SettlementAmt, transactionUtcDate: t.TxnUtcDT, diff --git a/test/portico-services/helpers-test.js b/test/portico-services/helpers-test.js index 4c61988..8784eed 100644 --- a/test/portico-services/helpers-test.js +++ b/test/portico-services/helpers-test.js @@ -73,9 +73,9 @@ var requestTypes = [ 'CreditReturn', 'CreditReversal', 'ReportActivity', - //'ReportBatchDetail', - //'ReportBatchHistory', - //'ReportBatchSummary', + 'ReportBatchDetail', + 'ReportBatchHistory', + 'ReportBatchSummary', //'ReportOpenAuths', 'ReportTxnDetail', 'ManageTokens' From 1cdf94b0d687d4ef4ed59f6c084f4dfdd69333f9 Mon Sep 17 00:00:00 2001 From: Felipe Polo-Wood Date: Tue, 4 Apr 2017 13:24:27 -0400 Subject: [PATCH 06/12] Fixed typo --- test/portico-services/helpers-test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/portico-services/helpers-test.js b/test/portico-services/helpers-test.js index 8784eed..6ec0ee2 100644 --- a/test/portico-services/helpers-test.js +++ b/test/portico-services/helpers-test.js @@ -49,7 +49,7 @@ exports.validateRequestTypes = { requestTypes.map(rt=>{ var rc = helpers.serviceNameToTransactionType(rt); var rc2 = helpers.transactionTypeToServiceName(rc); - assert.notEqual(rc,null,rt + ' should be a valid Service Name'); + assert.notEqual(rc2,null,rt + ' should be a valid Service Name'); assert.equal(rt,rc2, rt + ' should be the same as ' + rc2); }); } From 855a8833131d55c3d0f7879e4513c155fe7410ea Mon Sep 17 00:00:00 2001 From: Felipe Polo-Wood Date: Tue, 4 Apr 2017 15:18:45 -0400 Subject: [PATCH 07/12] Fixed Logic error and tests --- lib/infrastructure/helpers.js | 5 +---- test/portico-services/helpers-test.js | 4 ++-- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/lib/infrastructure/helpers.js b/lib/infrastructure/helpers.js index 2499999..89ff38c 100644 --- a/lib/infrastructure/helpers.js +++ b/lib/infrastructure/helpers.js @@ -16,15 +16,12 @@ function isEmptyObject(o){ if (o === null){ return true; } - if (o.length===0){ + if (typeof(o)==='object'&&o.length===0){ return true; } if (JSON.stringify(o)==="{}"){ return true; } - if (typeof(o)!=='object'){ - return true; - } return false; } diff --git a/test/portico-services/helpers-test.js b/test/portico-services/helpers-test.js index 6ec0ee2..87ca494 100644 --- a/test/portico-services/helpers-test.js +++ b/test/portico-services/helpers-test.js @@ -17,12 +17,12 @@ exports.isEmptyObject = { onNotObject: function() { var rc = helpers.isEmptyObject(''); - assert.equal(rc,true,'\'\' should return true'); + assert.equal(rc,false,'\'\' should return false'); }, onString: function(){ var rc = helpers.isEmptyObject(' '); - assert.equal(rc,true,'\' \' should return true'); + assert.equal(rc,false,'\' \' should return false'); }, onNotEmpty: function(){ From eb9c51b9692b03bca475f26bd8cfe0ec64841e37 Mon Sep 17 00:00:00 2001 From: Felipe Polo-Wood Date: Tue, 4 Apr 2017 17:47:37 -0400 Subject: [PATCH 08/12] Fixed Logic error and tests --- test/portico-services/helpers-test.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/portico-services/helpers-test.js b/test/portico-services/helpers-test.js index 87ca494..387440a 100644 --- a/test/portico-services/helpers-test.js +++ b/test/portico-services/helpers-test.js @@ -36,6 +36,7 @@ exports.validateRequestTypes = { requestTypes.map(rt=>{ var rc = schema.requestType(rt); assert.equal(helpers.isEmptyObject(rc),false, rt + ' should be a valid type'); + assert.equal(isRequestObject(rc),true, rt + ' should be a valid request object'); }); }, validTransactions: function(){ @@ -58,7 +59,7 @@ exports.validateRequestTypes = { function isRequestObject(o){ var rc = false; if (!helpers.isEmptyObject(o)){ - if (o.type==='object'&&!isEmptyObject(o.properties)){ + if (o.type==='object'&&!helpers.isEmptyObject(o.properties)){ rc = true; } } From f95fcae3cf7de1fc204e4c96841071d9c59401a3 Mon Sep 17 00:00:00 2001 From: Felipe Polo-Wood Date: Tue, 11 Apr 2017 07:42:14 -0400 Subject: [PATCH 09/12] pass status downstream --- lib/services/secure-submit/hps-credit-service.js | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/services/secure-submit/hps-credit-service.js b/lib/services/secure-submit/hps-credit-service.js index 6fb4830..b33cb4f 100644 --- a/lib/services/secure-submit/hps-credit-service.js +++ b/lib/services/secure-submit/hps-credit-service.js @@ -863,6 +863,7 @@ function HpsCreditService(hpsConfig, soapUri) { responseText: hlp.isEmptyObject(t.IssuerRspText)?(hlp.isEmptyObject(t.GatewayRspMsg)?'':t.GatewayRspMsg):t.IssuerRspText, amount: t.Amt, settlementAmount: t.SettlementAmt, + status: t.status, transactionUtcDate: t.TxnUtcDT, transactionType: filterBy || hlp.serviceNameToTransactionType(t.ServiceName), exceptions: (t.GatewayRspCode !== '0' || t.IssuerRspCode !== '00') ? { From 91125e57ebaebf25bff603d4bb32d8cc556d5f3f Mon Sep 17 00:00:00 2001 From: Felipe Polo-Wood Date: Tue, 11 Apr 2017 12:39:31 -0400 Subject: [PATCH 10/12] Fix SettlementAmnt to come from Data --- lib/services/secure-submit/hps-credit-service.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/services/secure-submit/hps-credit-service.js b/lib/services/secure-submit/hps-credit-service.js index b33cb4f..1bbfa94 100644 --- a/lib/services/secure-submit/hps-credit-service.js +++ b/lib/services/secure-submit/hps-credit-service.js @@ -949,7 +949,7 @@ function HpsCreditService(hpsConfig, soapUri) { result = { transactionId: t.GatewayTxnId, originalTransactionId: t.OriginalGatewayTxnId, - settlementAmount: t.SettlementAmt, + settlementAmount: t.Data.SettlementAmt, authorizedAmount: t.Data.AuthAmt, authorizationCode: t.Data.AuthCode, avsResultCode: t.Data.AVSRsltCode, From 28c94bf007eab9d122f8cd40947f1225c0908258 Mon Sep 17 00:00:00 2001 From: Felipe Polo-Wood Date: Mon, 24 Apr 2017 22:13:21 -0400 Subject: [PATCH 11/12] Enable TrackData --- .../secure-submit/hps-credit-service.js | 22 +++++++++++++------ 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/lib/services/secure-submit/hps-credit-service.js b/lib/services/secure-submit/hps-credit-service.js index 1bbfa94..79a2f5d 100644 --- a/lib/services/secure-submit/hps-credit-service.js +++ b/lib/services/secure-submit/hps-credit-service.js @@ -56,7 +56,13 @@ function HpsCreditService(hpsConfig, soapUri) { if (hlp.defNn(card)) { tx.CardData = {}; - tx.CardData.ManualEntry = hlp.hydrateCardData(card); + if (typeof(card)==='string'){ + tx.CardData.TrackData = card; + } else { + tx.CardData.ManualEntry = hlp.hydrateCardData(card); + schema.properties.CardData.required = ['ManualEntry']; + schema.properties.CardData.properties.ManualEntry.required = ['CardNbr', 'ExpMonth', 'ExpYear', 'CVV2']; + } if(hlp.defNn(requestMultiUseToken)) tx.CardData.TokenRequest = (requestMultiUseToken === true) ? 'Y': 'N'; } if (hlp.defNn(amount)) tx.Amt = amount; @@ -65,8 +71,6 @@ function HpsCreditService(hpsConfig, soapUri) { tx.AllowDup = 'Y'; schema.required = ['Amt']; - schema.properties.CardData.required = ['ManualEntry']; - schema.properties.CardData.properties.ManualEntry.required = ['CardNbr', 'ExpMonth', 'ExpYear', 'CVV2']; if (tv4.validate(tx, schema)) { gateway.submitTransaction({'CreditSale':{'Block1':tx}}, function (err, result) { @@ -197,7 +201,13 @@ function HpsCreditService(hpsConfig, soapUri) { if (hlp.defNn(card)) { tx.CardData = {}; - tx.CardData.ManualEntry = hlp.hydrateCardData(card); + if (typeof(card)==='string'){ + tx.CardData.TrackData = card; + } else { + tx.CardData.ManualEntry = hlp.hydrateCardData(card); + schema.properties.CardData.required = ['ManualEntry']; + schema.properties.CardData.properties.ManualEntry.required = ['CardNbr', 'ExpMonth', 'ExpYear', 'CVV2']; + } if(hlp.defNn(requestMultiUseToken)) tx.CardData.TokenRequest = (requestMultiUseToken === true) ? 'Y': 'N'; } if (hlp.defNn(amount)) tx.Amt = amount; @@ -206,8 +216,6 @@ function HpsCreditService(hpsConfig, soapUri) { tx.AllowDup = 'Y'; schema.required = ['Amt']; - schema.properties.CardData.required = ['ManualEntry']; - schema.properties.CardData.properties.ManualEntry.required = ['CardNbr', 'ExpMonth', 'ExpYear']; if (tv4.validate(tx, schema)) { gateway.submitTransaction({'CreditAuth':{'Block1':tx}}, function (err, result) { @@ -863,7 +871,7 @@ function HpsCreditService(hpsConfig, soapUri) { responseText: hlp.isEmptyObject(t.IssuerRspText)?(hlp.isEmptyObject(t.GatewayRspMsg)?'':t.GatewayRspMsg):t.IssuerRspText, amount: t.Amt, settlementAmount: t.SettlementAmt, - status: t.status, + status: t.Status, transactionUtcDate: t.TxnUtcDT, transactionType: filterBy || hlp.serviceNameToTransactionType(t.ServiceName), exceptions: (t.GatewayRspCode !== '0' || t.IssuerRspCode !== '00') ? { From 58755c6626ad576a2f76114a5fc21c113de26354 Mon Sep 17 00:00:00 2001 From: Felipe Polo-Wood Date: Tue, 25 Apr 2017 19:56:21 -0400 Subject: [PATCH 12/12] hydrated additional Txn Fields --- lib/infrastructure/helpers.js | 15 +++++++++++++++ lib/services/secure-submit/hps-credit-service.js | 16 ++++++++-------- 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/lib/infrastructure/helpers.js b/lib/infrastructure/helpers.js index 89ff38c..7bed463 100644 --- a/lib/infrastructure/helpers.js +++ b/lib/infrastructure/helpers.js @@ -55,6 +55,21 @@ var Helpers = { return undefined; }, + hydrateAdditionalTxnFields: + function hydrateAdditionalTxnFields(obj){ + var result = {}; + if (typeof(obj)==='string'){ + obj = {'description':obj}; + } + if (obj) { + if (objProp(obj,'description')) { result.Description = obj.description; } + if (objProp(obj,'invoiceId')) { result.InvoiceNbr = obj.invoiceId; } + if (objProp(obj,'customerId')) { result.CustomerId = obj.customerId; } + return result; + } + return undefined; + }, + hydrateCardHolderData: function hydrateCardHolderData(cardHolder) { var result = {}; diff --git a/lib/services/secure-submit/hps-credit-service.js b/lib/services/secure-submit/hps-credit-service.js index 79a2f5d..1a5c939 100644 --- a/lib/services/secure-submit/hps-credit-service.js +++ b/lib/services/secure-submit/hps-credit-service.js @@ -50,7 +50,7 @@ function HpsCreditService(hpsConfig, soapUri) { * @return {Object} exports for chaining */ var chargeWithCard = - function chargeWithCard(amount, currency, card, cardHolder, requestMultiUseToken, memo, callback) { + function chargeWithCard(amount, currency, card, cardHolder, requestMultiUseToken, additionalTxnFields, callback) { var schema = porticoSchema.requestType('CreditSale'), tx = {}; @@ -65,9 +65,9 @@ function HpsCreditService(hpsConfig, soapUri) { } if(hlp.defNn(requestMultiUseToken)) tx.CardData.TokenRequest = (requestMultiUseToken === true) ? 'Y': 'N'; } - if (hlp.defNn(amount)) tx.Amt = amount; - if (hlp.defNn(cardHolder)) tx.CardHolderData = hlp.hydrateCardHolderData(cardHolder); - if (hlp.defNn(memo)) tx.AdditionalTxnFields = { 'Description': memo }; + if (hlp.defNn(amount)) tx.Amt = amount; + if (hlp.defNn(cardHolder)) tx.CardHolderData = hlp.hydrateCardHolderData(cardHolder); + if (hlp.defNn(additionalTxnFields)) tx.AdditionalTxnFields = hlp.hydrateAdditionalTxnFields(additionalTxnFields); tx.AllowDup = 'Y'; schema.required = ['Amt']; @@ -195,7 +195,7 @@ function HpsCreditService(hpsConfig, soapUri) { * @return {Object} exports for chaining */ var authorizeWithCard = - function authorizeWithCard(amount, currency, card, cardHolder, requestMultiUseToken, memo, callback) { + function authorizeWithCard(amount, currency, card, cardHolder, requestMultiUseToken, additionalTxnFields, callback) { var schema = porticoSchema.requestType('CreditAuth'), tx = {}; @@ -210,9 +210,9 @@ function HpsCreditService(hpsConfig, soapUri) { } if(hlp.defNn(requestMultiUseToken)) tx.CardData.TokenRequest = (requestMultiUseToken === true) ? 'Y': 'N'; } - if (hlp.defNn(amount)) tx.Amt = amount; - if (hlp.defNn(cardHolder)) tx.CardHolderData = hlp.hydrateCardHolderData(cardHolder); - if (hlp.defNn(memo)) tx.AdditionalTxnFields = { 'Description': memo }; + if (hlp.defNn(amount)) tx.Amt = amount; + if (hlp.defNn(cardHolder)) tx.CardHolderData = hlp.hydrateCardHolderData(cardHolder); + if (hlp.defNn(additionalTxnFields)) tx.AdditionalTxnFields = hlp.hydrateAdditionalTxnFields(additionalTxnFields); tx.AllowDup = 'Y'; schema.required = ['Amt'];