Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[PAYOP-1116] Implement Larky function for rendering network token #326

Conversation

fangpenlin
Copy link
Contributor

@fangpenlin fangpenlin commented Mar 14, 2023

Fixes PAYOP-1116

Description of changes in release / Impact of release:

Implement Larky function for rendering network token

Documentation

Created a new network token module with service interface to be implemented later.

Risks of this release

The default module service either NoopNetworkTokenService or MockNetworkTokenService basically does nothing so shouldn't introduce any risk.

Is this a breaking change?

  • Yes
  • No

Is there a way to disable the change?

  • Use previous release
  • Use a feature flag
  • No

@fangpenlin fangpenlin changed the title WIP [PAYOP-1116] Implement Larky function for rendering network token [PAYOP-1116] Implement Larky function for rendering network token Mar 14, 2023
larky/pom.xml Outdated Show resolved Hide resolved
* @param thread Starlark thread object
* @return
*/
Object render(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All this Object makes me cringe

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't like passing Objects around, either. But cannot think of a better way to deal with it for now, open to suggestions 🙏

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

String?

pan="$.paymentMethod.number",
exp_month="$.paymentMethod.expiryMonth",
exp_year="$.paymentMethod.expiryYear",
cryptogram_value="$.mpiData.cavv",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

seems like string here

Copy link
Contributor

@mjallday mjallday left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks great! @mottersheadt to review the test please

named = true,
defaultValue = "None",
doc =
"JSONPath to insert the expire year from network token to the input payload and return",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"JSONPath to insert the expire year from network token to the input payload and return",
"JSONPath to insert the expiration year of the network token within the input payload",

"shopperReference": "YOUR_SHOPPER_REFERENCE",
"recurringProcessingModel": "CardOnFile",
"shopperInteraction": "Ecommerce",
# Deep JSONPath is not supported by the JSONPath lib, so that we need to
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@liddellc need to ensure we document this

load("@vgs//nts", "nts")


def _test_render():
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fantastic test. nice job @fangpenlin

lambda: nts.render(input, "$.pan", **{key: "$.not_exists"}),
(
'JSONPath "\\$\\.not_exists" does not exist, if you want to insert value to a nested path, please ensure that the ' +
"target value already exists at the given path in the input")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"please ensure that an empty element..."? may read better

input = {
"pan": "NOT_FOUND",
}
asserts.assert_fails(lambda: nts.render(input, "$.pan"), "network token does not found")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
asserts.assert_fails(lambda: nts.render(input, "$.pan"), "network token does not found")
asserts.assert_fails(lambda: nts.render(input, "$.pan"), "network token is not found")

name = "pan",
named = true,
doc =
"JSONPath to the PAN alias in the input payload for looking up the corresponding network token to be used and replace the original value at given JSONPath",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"JSONPath to the PAN alias in the input payload for looking up the corresponding network token to be used and replace the original value at given JSONPath",
"JSONPath to the PAN alias in the input payload. Used to look up the corresponding network token to be rendered and injected into the payload",

named = true,
defaultValue = "None",
doc =
"JSONPath to insert the expire month from network token to the input payload and return",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"JSONPath to insert the expire month from network token to the input payload and return",
"JSONPath to insert the expiration month of the network token within the input payload",

named = true,
defaultValue = "None",
doc =
"JSONPath to insert the cryptogram value from network token to the input payload and return",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"JSONPath to insert the cryptogram value from network token to the input payload and return",
"JSONPath to insert the cryptogram value of the network token within the input payload",

named = true,
defaultValue = "None",
doc =
"JSONPath to insert the cryptogram eci from network token to the input payload and return",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"JSONPath to insert the cryptogram eci from network token to the input payload and return",
"JSONPath to insert the cryptogram ECI of the network token within the input payload",

throw new RuntimeException(
Starlark.errorf(
"JSONPath \"%s\" does not exist, if you want to insert value to a nested path, please ensure "
+ "that the target value already exists at the given path in the input",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
+ "that the target value already exists at the given path in the input",
+ "that an empty value already exists at the given path in the input",

@mjallday mjallday requested a review from mottersheadt March 14, 2023 20:36
@fangpenlin
Copy link
Contributor Author

@mjallday FYI, I realized that Mahmoud tried pretty hard to reduce the dependencies of this project and keep the cpu and memory footprint low. I also realized there was a security bug in the json path before

json-path/JsonPath#687

There's a pure larky json path to be used as well:

https://github.com/verygoodsecurity/starlarky/blob/master/larky/src/main/resources/vendor/jsonpath_ng.star

I wonder maybe it would be way more secure to keep the java module as simple as possible and leave all the json path stuff in larky land. With that idea in mind I created an alt implemented here:

#327

the interface reminds the same

}
}

output = nts.render(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is great, but I have some thoughts.

  1. Can we return an object that the Larky script can use to input the values itself, rather than relying on the templatized rendering method? For example:
network_token_data = nts.render(input['paymentMethod']['number'])
input['mpiData']['cavv'] = network_token_data.cryptogram
input['mpiData']['eci'] = network_token_data.eci
input['paymentMethod']['expiryYear'] = network_token_data.expiry_year
input['paymentMethod']['expiryMonth'] = network_token_data.expiry_month
input['paymentMethod']['number'] = network_token_data.DPAN

With the current approach, I'm worried about any complex integrations. I'm not sure how this approach would work with form data, XML, graphql, etc... By providing the data right to the integration, I think the integration level code will be easier to implement in each circumstance.

  1. If we do stick with the templatized rendering approach, we need to ensure that the end-user doesn't need to send the "TO_BE_REPLACED" fields. If the field doesn't exist, I would expect it to be auto-created. Again need to account for how this would work with a graphql API (which I recently had to work with, hence being top of mind :) )

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hey, here it is an alternative version #327

@fangpenlin
Copy link
Contributor Author

close in favor of #327 instead

@fangpenlin fangpenlin closed this Mar 20, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants