-
Notifications
You must be signed in to change notification settings - Fork 2.5k
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
Elavon: Update Stored Credential behavior #5031
Conversation
@@ -46,7 +46,7 @@ def purchase(money, payment_method, options = {}) | |||
if payment_method.is_a?(String) | |||
add_token(xml, payment_method) | |||
else | |||
add_creditcard(xml, payment_method) | |||
add_creditcard(xml, payment_method) unless options[:ssl_token] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Elavon indicated that card number should not be added in addition to a token.
add_token(xml, payment_method) | ||
else | ||
add_creditcard(xml, payment_method) unless options[:ssl_token] | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Adds support for Authorize transctions with a token. I'm not sure why this wasn't added originally.
return options[:entry_mode] if options[:entry_mode] | ||
return 12 if options[:stored_credential] | ||
return if payment_method.is_a?(String) | ||
return 12 if options.dig(:stored_credential, :reason_type) == 'unscheduled' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Elavon indicated that this should only be 12 for unscheduled reason types. It's also only needed for pass-in cards, not tokens. But we retain the ability to override it with an option param.
xml.ssl_oar_data oar_data unless oar_data.nil? || oar_data.empty? | ||
xml.ssl_ps2000_data ps2000_data unless ps2000_data.nil? || ps2000_data.empty? | ||
xml.ssl_oar_data oar_data unless oar_data.nil? || oar_data.empty? || payment_method.is_a?(String) | ||
xml.ssl_ps2000_data ps2000_data unless ps2000_data.nil? || ps2000_data.empty? || payment_method.is_a?(String) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This prevents this data from being added for tokens, if it is also present.
xml.ssl_recurring_flag recurring_flag(options) if recurring_flag(options) | ||
xml.ssl_approval_code options[:approval_code] if options[:approval_code] && !payment_method.is_a?(String) | ||
xml.ssl_par_value options[:par_value] if options[:par_value] | ||
xml.ssl_association_token_data options[:association_token_data] if options[:association_token_data] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Two new values that may be present on an initial transaction that should be passed in subsequent COF transactions.
def recurring_flag(options) | ||
return unless reason = options.dig(:stored_credential, :reason_type) | ||
return 1 if reason == 'recurring' | ||
return 2 if reason == 'installment' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the primary new requirement for indicating recurring txns.
end | ||
|
||
def merchant_initiated_unscheduled(options) | ||
return options[:merchant_initiated_unscheduled] if options[:merchant_initiated_unscheduled] | ||
return 'Y' if options.dig(:stored_credential, :initiator) == 'merchant' && options.dig(:stored_credential, :reason_type) == 'unscheduled' || options.dig(:stored_credential, :reason_type) == 'recurring' | ||
return 'Y' if options.dig(:stored_credential, :initiator) == 'merchant' && options.dig(:stored_credential, :reason_type) == 'unscheduled' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should only be present for reason type unscheduled, not recurring.
If you haven't already please don't forget to run |
Yes, fixing those now! |
01a89b6
to
2cfc40f
Compare
Updated with Rubocop fixes. |
f1730e3
to
952c79d
Compare
Added tests for the combination of stored cred fields and using a manual token instead of a stored card authorization string. |
end | ||
xml.ssl_recurring_flag recurring_flag(options) if recurring_flag(options) | ||
xml.ssl_approval_code options[:approval_code] if options[:approval_code] && !payment_method.is_a?(String) && !options[:ssl_token] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we make this into a variable so it can also be used above? Where we check for payment_method.is_a?(String)
in ssl_oar_data
and ssl_ps2000_data
. Maybe the the new variable could be called used_payment_token
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good suggestion, I've done some refactoring of this method to clean it up in general which should help.
952c79d
to
9fb65d7
Compare
xml.ssl_par_value options[:par_value] if options[:par_value] | ||
xml.ssl_association_token_data options[:association_token_data] if options[:association_token_data] | ||
|
||
if !payment_method.is_a?(String) && !options[:ssl_token].present? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could this to be unless
instead of if
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks great! Thanks for all the hard work you put in!
9fb65d7
to
0079e93
Compare
0079e93
to
645d5b3
Compare
@almalee24 Made some changes after feedback from Elavon - notably to make sure we don't send cvv on non-initial stored cred txns, and ensuring a blank ps2000 data field was not passed in some situations, as well as being able to invoke real respones for the new par_value and association_token_data fields. |
@@ -234,8 +239,11 @@ def add_token(xml, token) | |||
xml.ssl_token token |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We probably need to update this method to either pass down options to grab token from there if payment is a credit card but has options[:ssl_token] or to return unless token.is_a?(String)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch... I thought I'd added enough test variations to cover that situation 😓
Oh wait, I think it didn't catch them because we have another place where we're adding ssl_token
in add_auth_purchase_params
😅
I'll see if I can unify those cases to prevent duplication and confusion.
ac0a73a
to
1954c69
Compare
Refactored all instances of adding card or token into a single helper method (update action needs both so adds them manually). Would appreciate another look at the diff. |
@@ -352,30 +353,48 @@ def add_line_items(xml, level_3_data) | |||
} | |||
end | |||
|
|||
def add_stored_credential(xml, options) | |||
def add_stored_credential(xml, payment_method, options) | |||
return unless options[:stored_credential] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not necessary since you already did if options[:stored_credential]
when calling the method
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
True, though I'd lean toward overeager guard clauses than less; if it gets used in the future it's already there.
Looks good to me! |
To satisfy new Elavon API requirements, including recurring_flag, approval_code for non-tokenized PMs, installment_count and _number, and situational par_value and association_token_data fields. This also now allows Authorize transactions with a token/stored card. Remote (Same 5 Failures on Master): 39 tests, 162 assertions, 5 failures, 0 errors, 0 pendings, 0 omissions, 0 notifications 87.1795% passed Unit: 53 tests, 298 assertions, 0 failures, 0 errors, 0 pendings, 0 omissions, 0 notifications 100% passed
1954c69
to
f39602f
Compare
To satisfy new Elavon API requirements, including recurring_flag, approval_code for non-tokenized PMs, installment_count and _number, and situational par_value and association_token_data fields.
This also now allows Authorize transactions with a token/stored card.
Remote (Same 5 Failures on Master):
39 tests, 162 assertions, 5 failures, 0 errors, 0 pendings, 0 omissions, 0 notifications 87.1795% passed
Unit:
53 tests, 298 assertions, 0 failures, 0 errors, 0 pendings, 0 omissions, 0 notifications 100% passed