-
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -42,41 +42,34 @@ def purchase(money, payment_method, options = {}) | |
xml.ssl_vendor_id @options[:ssl_vendor_id] || options[:ssl_vendor_id] | ||
xml.ssl_transaction_type self.actions[:purchase] | ||
xml.ssl_amount amount(money) | ||
|
||
if payment_method.is_a?(String) | ||
add_token(xml, payment_method) | ||
else | ||
add_creditcard(xml, payment_method) | ||
end | ||
|
||
add_token_or_card(xml, payment_method, options) | ||
add_invoice(xml, options) | ||
add_salestax(xml, options) | ||
add_currency(xml, money, options) | ||
add_address(xml, options) | ||
add_customer_email(xml, options) | ||
add_test_mode(xml, options) | ||
add_ip(xml, options) | ||
add_auth_purchase_params(xml, options) | ||
add_auth_purchase_params(xml, payment_method, options) | ||
add_level_3_fields(xml, options) if options[:level_3_data] | ||
end | ||
commit(request) | ||
end | ||
|
||
def authorize(money, creditcard, options = {}) | ||
def authorize(money, payment_method, options = {}) | ||
request = build_xml_request do |xml| | ||
xml.ssl_vendor_id @options[:ssl_vendor_id] || options[:ssl_vendor_id] | ||
xml.ssl_transaction_type self.actions[:authorize] | ||
xml.ssl_amount amount(money) | ||
|
||
add_salestax(xml, options) | ||
add_token_or_card(xml, payment_method, options) | ||
add_invoice(xml, options) | ||
add_creditcard(xml, creditcard) | ||
add_salestax(xml, options) | ||
add_currency(xml, money, options) | ||
add_address(xml, options) | ||
add_customer_email(xml, options) | ||
add_test_mode(xml, options) | ||
add_ip(xml, options) | ||
add_auth_purchase_params(xml, options) | ||
add_auth_purchase_params(xml, payment_method, options) | ||
add_level_3_fields(xml, options) if options[:level_3_data] | ||
end | ||
commit(request) | ||
|
@@ -92,7 +85,7 @@ def capture(money, authorization, options = {}) | |
add_salestax(xml, options) | ||
add_approval_code(xml, authorization) | ||
add_invoice(xml, options) | ||
add_creditcard(xml, options[:credit_card]) | ||
add_creditcard(xml, options[:credit_card], options) | ||
add_currency(xml, money, options) | ||
add_address(xml, options) | ||
add_customer_email(xml, options) | ||
|
@@ -139,7 +132,7 @@ def credit(money, creditcard, options = {}) | |
xml.ssl_transaction_type self.actions[:credit] | ||
xml.ssl_amount amount(money) | ||
add_invoice(xml, options) | ||
add_creditcard(xml, creditcard) | ||
add_creditcard(xml, creditcard, options) | ||
add_currency(xml, money, options) | ||
add_address(xml, options) | ||
add_customer_email(xml, options) | ||
|
@@ -152,7 +145,7 @@ def verify(credit_card, options = {}) | |
request = build_xml_request do |xml| | ||
xml.ssl_vendor_id @options[:ssl_vendor_id] || options[:ssl_vendor_id] | ||
xml.ssl_transaction_type self.actions[:verify] | ||
add_creditcard(xml, credit_card) | ||
add_creditcard(xml, credit_card, options) | ||
add_address(xml, options) | ||
add_test_mode(xml, options) | ||
add_ip(xml, options) | ||
|
@@ -165,7 +158,7 @@ def store(creditcard, options = {}) | |
xml.ssl_vendor_id @options[:ssl_vendor_id] || options[:ssl_vendor_id] | ||
xml.ssl_transaction_type self.actions[:store] | ||
xml.ssl_add_token 'Y' | ||
add_creditcard(xml, creditcard) | ||
add_creditcard(xml, creditcard, options) | ||
add_address(xml, options) | ||
add_customer_email(xml, options) | ||
add_test_mode(xml, options) | ||
|
@@ -174,12 +167,12 @@ def store(creditcard, options = {}) | |
commit(request) | ||
end | ||
|
||
def update(token, creditcard, options = {}) | ||
def update(token, payment_method, options = {}) | ||
request = build_xml_request do |xml| | ||
xml.ssl_vendor_id @options[:ssl_vendor_id] || options[:ssl_vendor_id] | ||
xml.ssl_transaction_type self.actions[:update] | ||
add_token(xml, token) | ||
add_creditcard(xml, creditcard) | ||
xml.ssl_token token | ||
add_creditcard(xml, payment_method, options) | ||
add_address(xml, options) | ||
add_customer_email(xml, options) | ||
add_test_mode(xml, options) | ||
|
@@ -200,6 +193,14 @@ def scrub(transcript) | |
|
||
private | ||
|
||
def add_token_or_card(xml, payment_method, options) | ||
if payment_method.is_a?(String) || options[:ssl_token] | ||
xml.ssl_token options[:ssl_token] || payment_method | ||
else | ||
add_creditcard(xml, payment_method, options) | ||
end | ||
end | ||
|
||
def add_invoice(xml, options) | ||
xml.ssl_invoice_number url_encode_truncate((options[:order_id] || options[:invoice]), 25) | ||
xml.ssl_description url_encode_truncate(options[:description], 255) | ||
|
@@ -213,11 +214,11 @@ def add_txn_id(xml, authorization) | |
xml.ssl_txn_id authorization.split(';').last | ||
end | ||
|
||
def add_creditcard(xml, creditcard) | ||
def add_creditcard(xml, creditcard, options) | ||
xml.ssl_card_number creditcard.number | ||
xml.ssl_exp_date expdate(creditcard) | ||
|
||
add_verification_value(xml, creditcard) if creditcard.verification_value? | ||
add_verification_value(xml, creditcard, options) | ||
|
||
xml.ssl_first_name url_encode_truncate(creditcard.first_name, 20) | ||
xml.ssl_last_name url_encode_truncate(creditcard.last_name, 30) | ||
|
@@ -230,12 +231,12 @@ def add_currency(xml, money, options) | |
xml.ssl_transaction_currency currency | ||
end | ||
|
||
def add_token(xml, token) | ||
xml.ssl_token token | ||
end | ||
def add_verification_value(xml, credit_card, options) | ||
return unless credit_card.verification_value? | ||
# Don't add cvv if this is a non-initial stored credential transaction | ||
return if options[:stored_credential] && !options[:stored_credential][:initial_transaction] | ||
|
||
def add_verification_value(xml, creditcard) | ||
xml.ssl_cvv2cvc2 creditcard.verification_value | ||
xml.ssl_cvv2cvc2 credit_card.verification_value | ||
xml.ssl_cvv2cvc2_indicator 1 | ||
end | ||
|
||
|
@@ -294,16 +295,16 @@ def add_ip(xml, options) | |
end | ||
|
||
# add_recurring_token is a field that can be sent in to obtain a token from Elavon for use with their tokenization program | ||
def add_auth_purchase_params(xml, options) | ||
def add_auth_purchase_params(xml, payment_method, options) | ||
xml.ssl_dynamic_dba options[:dba] if options.has_key?(:dba) | ||
xml.ssl_merchant_initiated_unscheduled merchant_initiated_unscheduled(options) if merchant_initiated_unscheduled(options) | ||
xml.ssl_add_token options[:add_recurring_token] if options.has_key?(:add_recurring_token) | ||
xml.ssl_token options[:ssl_token] if options[:ssl_token] | ||
xml.ssl_customer_code options[:customer] if options.has_key?(:customer) | ||
xml.ssl_customer_number options[:customer_number] if options.has_key?(:customer_number) | ||
xml.ssl_entry_mode entry_mode(options) if entry_mode(options) | ||
xml.ssl_entry_mode add_entry_mode(payment_method, options) if add_entry_mode(payment_method, options) | ||
add_custom_fields(xml, options) if options[:custom_fields] | ||
add_stored_credential(xml, options) if options[:stored_credential] | ||
add_stored_credential(xml, payment_method, options) if options[:stored_credential] | ||
add_installment_fields(xml, options) if options.dig(:stored_credential, :reason_type) == 'installment' | ||
end | ||
|
||
def add_custom_fields(xml, options) | ||
|
@@ -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] | ||
|
||
network_transaction_id = options.dig(:stored_credential, :network_transaction_id) | ||
case | ||
when network_transaction_id.nil? | ||
return | ||
when network_transaction_id.to_s.include?('|') | ||
oar_data, ps2000_data = options[:stored_credential][:network_transaction_id].split('|') | ||
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? | ||
when network_transaction_id.to_s.length > 22 | ||
xml.ssl_oar_data options.dig(:stored_credential, :network_transaction_id) | ||
else | ||
xml.ssl_ps2000_data options.dig(:stored_credential, :network_transaction_id) | ||
xml.ssl_recurring_flag recurring_flag(options) if recurring_flag(options) | ||
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 commentThe 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. |
||
|
||
unless payment_method.is_a?(String) || options[:ssl_token].present? | ||
xml.ssl_approval_code options[:approval_code] if options[:approval_code] | ||
if network_transaction_id.to_s.include?('|') | ||
oar_data, ps2000_data = network_transaction_id.split('|') | ||
xml.ssl_oar_data oar_data unless oar_data.blank? | ||
xml.ssl_ps2000_data ps2000_data unless ps2000_data.blank? | ||
elsif network_transaction_id.to_s.length > 22 | ||
xml.ssl_oar_data network_transaction_id | ||
elsif network_transaction_id.present? | ||
xml.ssl_ps2000_data network_transaction_id | ||
end | ||
end | ||
end | ||
|
||
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 commentThe 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 commentThe reason will be displayed to describe this comment to others. Learn more. Should only be present for reason type unscheduled, not recurring. |
||
end | ||
|
||
def add_installment_fields(xml, options) | ||
xml.ssl_payment_number options[:payment_number] | ||
xml.ssl_payment_count options[:installments] | ||
end | ||
|
||
def entry_mode(options) | ||
def add_entry_mode(payment_method, options) | ||
return options[:entry_mode] if options[:entry_mode] | ||
return 12 if options[:stored_credential] | ||
return if payment_method.is_a?(String) || options[:ssl_token] | ||
return 12 if options.dig(:stored_credential, :reason_type) == 'unscheduled' | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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. |
||
end | ||
|
||
def build_xml_request | ||
|
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 methodThere 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.