diff --git a/larky/src/main/java/com/verygood/security/larky/modules/NetworkTokenModule.java b/larky/src/main/java/com/verygood/security/larky/modules/NetworkTokenModule.java index e7eb1aa12..f85651c30 100644 --- a/larky/src/main/java/com/verygood/security/larky/modules/NetworkTokenModule.java +++ b/larky/src/main/java/com/verygood/security/larky/modules/NetworkTokenModule.java @@ -87,9 +87,9 @@ public NetworkTokenModule() { defaultValue = "'TAVV'", allowedTypes = {@ParamType(type = String.class)}), @Param( - name = "merchant_id", + name = "vgs_merchant_id", named = true, - doc = "Merchant id to get a network token for", + doc = "VGS merchant id to get a network token for", defaultValue = "''", allowedTypes = {@ParamType(type = String.class)}), }) @@ -100,7 +100,7 @@ public Dict getNetworkToken( String amount, String currencyCode, String cryptogramType, - String merchantId, + String vgsMerchantId, StarlarkThread thread) throws EvalException { if (pan.trim().isEmpty()) { @@ -109,7 +109,8 @@ public Dict getNetworkToken( final Optional networkTokenOptional; try { networkTokenOptional = - networkTokenService.getNetworkToken(pan, cvv, amount, currencyCode, cryptogramType, merchantId); + networkTokenService.getNetworkToken(pan, cvv, amount, currencyCode, cryptogramType, + vgsMerchantId); } catch (UnsupportedOperationException exception) { throw Starlark.errorf("nts.get_network_token operation must be overridden"); } diff --git a/larky/src/main/java/com/verygood/security/larky/modules/vgs/nts/LarkyNetworkToken.java b/larky/src/main/java/com/verygood/security/larky/modules/vgs/nts/LarkyNetworkToken.java index 7bc0e1593..82844036c 100644 --- a/larky/src/main/java/com/verygood/security/larky/modules/vgs/nts/LarkyNetworkToken.java +++ b/larky/src/main/java/com/verygood/security/larky/modules/vgs/nts/LarkyNetworkToken.java @@ -14,6 +14,7 @@ public interface LarkyNetworkToken extends StarlarkValue { * @param amount amount of payment for retrieving cryptogram * @param currencyCode currency code of payment for retrieving cryptogram * @param cryptogramType type of cryptogram + * @param vgsMerchantId vgs merchant public identifier * @param thread Starlark thread object * @return a dict contains the network token values */ @@ -23,7 +24,7 @@ Dict getNetworkToken( String amount, String currencyCode, String cryptogramType, - String merchantId, + String vgsMerchantId, StarlarkThread thread) throws EvalException; } diff --git a/larky/src/main/java/com/verygood/security/larky/modules/vgs/nts/MockNetworkTokenService.java b/larky/src/main/java/com/verygood/security/larky/modules/vgs/nts/MockNetworkTokenService.java index 06dc46666..38648603b 100644 --- a/larky/src/main/java/com/verygood/security/larky/modules/vgs/nts/MockNetworkTokenService.java +++ b/larky/src/main/java/com/verygood/security/larky/modules/vgs/nts/MockNetworkTokenService.java @@ -26,20 +26,20 @@ public class MockNetworkTokenService implements NetworkTokenService { @Override public Optional getNetworkToken( String panAlias, String cvv, String amount, String currencyCode, String cryptogramType, - String merchantId) { + String vgsMerchantId) { if (panAlias.equals("NOT_FOUND")) { return Optional.empty(); } - if (StringUtils.isBlank(merchantId)) { + if (StringUtils.isBlank(vgsMerchantId)) { return Optional.of( getForDefaultMerchant(cryptogramType) ); } - if (!NETWORK_TOKENS.containsKey(merchantId)) { + if (!NETWORK_TOKENS.containsKey(vgsMerchantId)) { return Optional.empty(); } final NetworkToken networkToken = - NETWORK_TOKENS.get(merchantId) + NETWORK_TOKENS.get(vgsMerchantId) .cryptogramValue( cryptogramType.equals("DTVV") ? "MOCK_DYNAMIC_CVV" : "MOCK_CRYPTOGRAM_VALUE") .cryptogramType(cryptogramType) diff --git a/larky/src/main/java/com/verygood/security/larky/modules/vgs/nts/NoopNetworkTokenService.java b/larky/src/main/java/com/verygood/security/larky/modules/vgs/nts/NoopNetworkTokenService.java index 929f8dc5d..cfa05b676 100644 --- a/larky/src/main/java/com/verygood/security/larky/modules/vgs/nts/NoopNetworkTokenService.java +++ b/larky/src/main/java/com/verygood/security/larky/modules/vgs/nts/NoopNetworkTokenService.java @@ -6,7 +6,7 @@ public class NoopNetworkTokenService implements NetworkTokenService { @Override public Optional getNetworkToken( - String panAlias, String cvv, String amount, String currencyCode, String cryptogramType, String merchantId) { + String panAlias, String cvv, String amount, String currencyCode, String cryptogramType, String vgsMerchantId) { throw new UnsupportedOperationException("Not implemented"); } } diff --git a/larky/src/main/resources/vgs/nts.star b/larky/src/main/resources/vgs/nts.star index 9537e4b44..391c7fdd5 100644 --- a/larky/src/main/resources/vgs/nts.star +++ b/larky/src/main/resources/vgs/nts.star @@ -34,7 +34,7 @@ def render( exp_year=None, cryptogram_value=None, cryptogram_eci=None, - merchant_id='', + vgs_merchant_id="", ): """Retrieves a network token for the given PAN alias, renders the cryptogram, and injects the network token values into the payload. @@ -73,7 +73,7 @@ def render( :param cryptogram_value: JSONPath to insert the cryptogram value of the network token within the input payload :param cryptogram_eci: JSONPath to insert the cryptogram ECI of the network token within the input payload - :param merchant_id: Merchant id to get a network token for + :param vgs_merchant_id: Merchant id to get a network token for :return: JSON payload injected with network token values """ pan_value = jsonpath_ng.parse(pan).find(input).value @@ -90,13 +90,18 @@ def render( if cvv_result != None and cvv_result.is_ok: cvv_value = cvv_result.unwrap() + vgs_merchant_id_value = \ + jsonpath_ng.parse(vgs_merchant_id).find(input).value \ + if vgs_merchant_id.startswith("$.") \ + else vgs_merchant_id + network_token = _nts.get_network_token( pan=pan_value, cvv=cvv_value, amount=amount_value, currency_code=currency_code_value, cryptogram_type="TAVV" if dcvv == None else "DTVV", - merchant_id=merchant_id, + vgs_merchant_id=vgs_merchant_id_value, ) placements = [ (pan, network_token["token"]), diff --git a/larky/src/test/resources/vgs_tests/nts/test_default_nts.star b/larky/src/test/resources/vgs_tests/nts/test_default_nts.star index 999b93a48..fc0d8c9ea 100644 --- a/larky/src/test/resources/vgs_tests/nts/test_default_nts.star +++ b/larky/src/test/resources/vgs_tests/nts/test_default_nts.star @@ -32,7 +32,8 @@ def _make_fixture(): "mpiData": { "cavv": "TO_BE_REPLACED", "eci": "TO_BE_REPLACED", - } + }, + "vgs_merchant_id": "MCdAhTydCJMZEzxgqhvVdkgo" } @@ -59,7 +60,7 @@ def _test_get_network_token_for_merchant(): cvv="MOCK_CVV", amount="123.45", currency_code="USD", - merchant_id="MCdAhTydCJMZEzxgqhvVdkgo", + vgs_merchant_id="MCdAhTydCJMZEzxgqhvVdkgo", ) asserts.assert_that(output).is_equal_to({ "token": "4111111111111111", @@ -133,7 +134,7 @@ def _test_render_for_merchant(): exp_year="$.paymentMethod.expiryYear", cryptogram_value="$.mpiData.cavv", cryptogram_eci="$.mpiData.eci", - merchant_id="MCdAhTydCJMZEzxgqhvVdkgo", + vgs_merchant_id="MCdAhTydCJMZEzxgqhvVdkgo", ) asserts.assert_that(output["paymentMethod"]["number"]).is_equal_to("4111111111111111") asserts.assert_that(output["paymentMethod"]["expiryMonth"]).is_equal_to(10) @@ -142,6 +143,44 @@ def _test_render_for_merchant(): asserts.assert_that(output["mpiData"]["eci"]).is_equal_to("MOCK_CRYPTOGRAM_ECI") +def _test_render_for_merchant_from_jsonpath(): + output = nts.render( + _make_fixture(), + pan="$.paymentMethod.number", + cvv="$.paymentMethod.cvv", + amount="$.amount.value", + currency_code="$.amount.currency", + exp_month="$.paymentMethod.expiryMonth", + exp_year="$.paymentMethod.expiryYear", + cryptogram_value="$.mpiData.cavv", + cryptogram_eci="$.mpiData.eci", + vgs_merchant_id="$.vgs_merchant_id", + ) + asserts.assert_that(output["paymentMethod"]["number"]).is_equal_to("4111111111111111") + asserts.assert_that(output["paymentMethod"]["expiryMonth"]).is_equal_to(10) + asserts.assert_that(output["paymentMethod"]["expiryYear"]).is_equal_to(27) + asserts.assert_that(output["mpiData"]["cavv"]).is_equal_to("MOCK_CRYPTOGRAM_VALUE") + asserts.assert_that(output["mpiData"]["eci"]).is_equal_to("MOCK_CRYPTOGRAM_ECI") + + +def _test_render_for_merchant_from_jsonpath_not_found(): + asserts.assert_fails( + lambda: nts.render( + _make_fixture(), + pan="$.paymentMethod.number", + cvv="$.paymentMethod.cvv", + amount="$.amount.value", + currency_code="$.amount.currency", + exp_month="$.paymentMethod.expiryMonth", + exp_year="$.paymentMethod.expiryYear", + cryptogram_value="$.mpiData.cavv", + cryptogram_eci="$.mpiData.eci", + vgs_merchant_id="$.unknown_vgs_merchant_id", + ), + 'Key "{unknown_vgs_merchant_id}" does not exist in node', + ) + + def _test_render_for_merchant_not_found(): asserts.assert_fails( lambda: nts.render( @@ -154,7 +193,7 @@ def _test_render_for_merchant_not_found(): exp_year="$.paymentMethod.expiryYear", cryptogram_value="$.mpiData.cavv", cryptogram_eci="$.mpiData.eci", - merchant_id="merchant_id_not_found", + vgs_merchant_id="vgs_merchant_id_not_found", ), "network token is not found", ) @@ -333,6 +372,8 @@ def _suite(): # Render tests _suite.addTest(unittest.FunctionTestCase(_test_render)) _suite.addTest(unittest.FunctionTestCase(_test_render_for_merchant)) + _suite.addTest(unittest.FunctionTestCase(_test_render_for_merchant_from_jsonpath)) + _suite.addTest(unittest.FunctionTestCase(_test_render_for_merchant_from_jsonpath_not_found)) _suite.addTest(unittest.FunctionTestCase(_test_render_for_merchant_not_found)) _suite.addTest(unittest.FunctionTestCase(_test_render_with_nested_safe)) _suite.addTest(unittest.FunctionTestCase(_test_render_without_cvv_value))