Skip to content

Commit

Permalink
Mundipagg: Append error messages to the message response field
Browse files Browse the repository at this point in the history
For purchase, authorize, and store, extract any error messages from the
gateway response and append them to the "message" response feld. Mundipagg
can return errors at either the top level of the response object, or under
the last_transaction gateway_response key.

CE-114

Unit:
4268 tests, 70604 assertions, 0 failures, 0 errors, 0 pendings, 2 omissions, 0 notifications
100% passed

Remote:
37 tests, 93 assertions, 0 failures, 0 errors, 0 pendings, 0 omissions, 0 notifications
100% passed
  • Loading branch information
Jason Nappier committed Sep 18, 2019
1 parent 5158361 commit b1e0807
Show file tree
Hide file tree
Showing 4 changed files with 256 additions and 5 deletions.
1 change: 1 addition & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
* TNS: Update verison and support pay mode [curiousepic] #3355
* Stripe: Add supported countries [therufs] #3358
* Stripe Payment Intents: Add supported countries [therufs] #3359
* Mundipagg: Append error messages to the message response field [jasonxp] #3353

== Version 1.98.0 (Sep 9, 2019)
* Stripe Payment Intents: Add new gateway [britth] #3290
Expand Down
37 changes: 32 additions & 5 deletions lib/active_merchant/billing/gateways/mundipagg.rb
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,8 @@ def commit(action, parameters, auth = nil)
error_code: error_code_from(response)
)
rescue ResponseError => e
message = get_error_message(e)
message = get_error_messages(e)

return Response.new(
false,
"#{STANDARD_ERROR_MESSAGE_MAPPING[e.response.code]} #{message}",
Expand All @@ -263,15 +264,41 @@ def success_from(response)
%w[pending paid processing canceled active].include? response['status']
end

def get_error_message(error)
JSON.parse(error.response.body)['message']
end

def message_from(response)
return gateway_response_errors(response) if gateway_response_errors?(response)
return response['message'] if response['message']
return response['last_transaction']['acquirer_message'] if response['last_transaction']
end

def get_error_messages(error)
parsed_response_body = parse(error.response.body)
message = parsed_response_body['message']

parsed_response_body['errors']&.each do |type, descriptions|
message += ' | '
message += descriptions.join(', ')
end

message
end

def gateway_response_errors?(response)
response.try(:[], 'last_transaction').try(:[], 'gateway_response').try(:[], 'errors').present?
end

def gateway_response_errors(response)
error_string = ''

response['last_transaction']['gateway_response']['errors']&.each do |error|
error.each do |key, value|
error_string += ' | ' unless error_string.blank?
error_string += value
end
end

error_string
end

def authorization_from(response, action)
return "#{response['customer']['id']}|#{response['id']}" if action == 'store'
response['id']
Expand Down
30 changes: 30 additions & 0 deletions test/remote/gateways/remote_mundipagg_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ def setup
billing_address: address({neighborhood: 'Sesame Street'}),
description: 'Store Purchase'
}

@excess_length_neighborhood = address({neighborhood: 'Super Long Neighborhood Name' * 5})
@neighborhood_length_error = 'Invalid parameters; The request is invalid. | The field neighborhood must be a string with a maximum length of 64.'
end

def test_successful_purchase
Expand Down Expand Up @@ -68,6 +71,15 @@ def test_failed_purchase
test_failed_purchase_with(@declined_card)
end

def test_failed_purchase_with_top_level_errors
@options[:billing_address] = @excess_length_neighborhood

response = @gateway.purchase(105200, @credit_card, @options)

assert_failure response
assert_equal @neighborhood_length_error, response.message
end

def test_failed_purchase_with_alelo_card
test_failed_purchase_with(@declined_alelo_voucher)
end
Expand All @@ -88,6 +100,15 @@ def test_failed_authorize_with_alelo_card
test_failed_authorize_with(@declined_alelo_voucher)
end

def test_failed_authorize_with_top_level_errors
@options[:billing_address] = @excess_length_neighborhood

response = @gateway.authorize(@amount, @credit_card, @options)

assert_failure response
assert_equal @neighborhood_length_error, response.message
end

def test_partial_capture
test_partial_capture_with(@credit_card)
end
Expand Down Expand Up @@ -190,6 +211,15 @@ def test_successful_store_and_purchase_with_alelo_card
test_successful_store_and_purchase_with(@alelo_voucher)
end

def test_failed_store_with_top_level_errors
@options[:billing_address] = @excess_length_neighborhood

response = @gateway.store(@credit_card, @options)

assert_failure response
assert_equal @neighborhood_length_error, response.message
end

def test_invalid_login
gateway = MundipaggGateway.new(api_key: '')

Expand Down
193 changes: 193 additions & 0 deletions test/unit/gateways/mundipagg_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ def setup
billing_address: address,
description: 'Store Purchase'
}

@gateway_response_error = 'Esta loja n??o possui um meio de pagamento configurado para a bandeira VR'
end

def test_successful_purchase
Expand Down Expand Up @@ -81,6 +83,23 @@ def test_failed_purchase
assert_equal Gateway::STANDARD_ERROR_CODE[:processing_error], response.error_code
end

def test_failed_purchase_with_top_level_errors
@gateway.expects(:ssl_post).raises(mock_response_error)

response = @gateway.purchase(@amount, @credit_card, @options)

assert_invalid_parameter_errors(response)
end

def test_failed_purchase_with_gateway_response_errors
@gateway.expects(:ssl_post).returns(failed_response_with_gateway_response_errors)

response = @gateway.purchase(@amount, @credit_card, @options)

assert_success response
assert_equal @gateway_response_error, response.message
end

def test_successful_authorize
@gateway.expects(:ssl_post).returns(successful_authorize_response)

Expand Down Expand Up @@ -113,6 +132,23 @@ def test_failed_authorize
assert_equal Gateway::STANDARD_ERROR_CODE[:processing_error], response.error_code
end

def test_failed_authorize_with_top_level_errors
@gateway.expects(:ssl_post).raises(mock_response_error)

response = @gateway.authorize(@amount, @credit_card, @options)

assert_invalid_parameter_errors(response)
end

def test_failed_authorize_with_gateway_response_errors
@gateway.expects(:ssl_post).returns(failed_response_with_gateway_response_errors)

response = @gateway.authorize(@amount, @credit_card, @options)

assert_success response
assert_equal @gateway_response_error, response.message
end

def test_successful_capture
@gateway.expects(:ssl_post).returns(successful_capture_response)

Expand Down Expand Up @@ -196,6 +232,23 @@ def test_sucessful_store
assert response.test?
end

def test_failed_store_with_top_level_errors
@gateway.expects(:ssl_post).times(2).raises(mock_response_error)

response = @gateway.store(@credit_card, @options)

assert_invalid_parameter_errors(response)
end

def test_failed_store_with_gateway_response_errors
@gateway.expects(:ssl_post).times(2).returns(failed_response_with_gateway_response_errors)

response = @gateway.store(@credit_card, @options)

assert_success response
assert_equal @gateway_response_error, response.message
end

def test_gateway_id_fallback
gateway = MundipaggGateway.new(api_key: 'my_api_key', gateway_id: 'abc123')
options = {
Expand Down Expand Up @@ -227,6 +280,22 @@ def test_successful_purchase_with(card)
assert response.test?
end

def mock_response_error
mock_response = Net::HTTPUnprocessableEntity.new('1.1', '422', 'Unprocessable Entity')
mock_response.stubs(:body).returns(failed_response_with_top_level_errors)

ActiveMerchant::ResponseError.new(mock_response)
end

def assert_invalid_parameter_errors(response)
assert_failure response

assert_equal(
'Invalid parameters; The request is invalid. | The field neighborhood must be a string with a maximum length of 64. | The field line_1 must be a string with a maximum length of 256.',
response.message
)
end

def pre_scrubbed
%q(
opening connection to api.mundipagg.com:443...
Expand Down Expand Up @@ -418,6 +487,130 @@ def failed_purchase_response
)
end

def failed_response_with_top_level_errors
%(
{
"message": "The request is invalid.",
"errors": {
"charge.payment.credit_card.card.billing_address.neighborhood": [
"The field neighborhood must be a string with a maximum length of 64."
],
"charge.payment.credit_card.card.billing_address.line_1": [
"The field line_1 must be a string with a maximum length of 256."
]
},
"request": {
"currency": "USD",
"amount": 100,
"customer": {
"name": "Longbob Longsen",
"phones": {},
"metadata": {}
},
"payment": {
"gateway_affiliation_id": "d76dffc8-c3e5-4d80-b9ee-dc8fb6c56c83",
"payment_method": "credit_card",
"credit_card": {
"installments": 1,
"capture": true,
"card": {
"last_four_digits": "2224",
"brand": "Visa",
"holder_name": "Longbob Longsen",
"exp_month": 9,
"exp_year": 2020,
"billing_address": {
"street": "My Street",
"number": "456",
"zip_code": "K1C2N6",
"neighborhood": "Sesame StreetSesame StreetSesame StreetSesame StreetSesame StreetSesame StreetSesame StreetSesame StreetSesame StreetSesame StreetSesame StreetSesame StreetSesame StreetSesame StreetSesame StreetSesame StreetSesame StreetSesame StreetSesame StreetSesame StreetSesame Street",
"city": "Ottawa",
"state": "ON",
"country": "CA",
"line_1": "456, My Street, Sesame StreetSesame StreetSesame StreetSesame StreetSesame StreetSesame StreetSesame StreetSesame StreetSesame StreetSesame StreetSesame StreetSesame StreetSesame StreetSesame StreetSesame StreetSesame StreetSesame StreetSesame StreetSesame StreetSesame StreetSesame Street"
},
"options": {}
}
},
"metadata": {
"mundipagg_payment_method_code": "1"
}
}
}
}
)
end

def failed_response_with_gateway_response_errors
%(
{
"id": "ch_90Vjq8TrwfP74XJO",
"code": "ME0KIN4A0O",
"gateway_id": "162bead8-23a0-4708-b687-078a69a1aa7c",
"amount": 100,
"paid_amount": 100,
"status": "paid",
"currency": "USD",
"payment_method": "credit_card",
"paid_at": "2018-02-01T18:41:05Z",
"created_at": "2018-02-01T18:41:04Z",
"updated_at": "2018-02-01T18:41:04Z",
"customer": {
"id": "cus_VxJX2NmTqyUnXgL9",
"name": "Longbob Longsen",
"email": "",
"delinquent": false,
"created_at": "2018-02-01T18:41:04Z",
"updated_at": "2018-02-01T18:41:04Z",
"phones": {}
},
"last_transaction": {
"id": "tran_JNzjzadcVZHlG8K2",
"transaction_type": "credit_card",
"gateway_id": "c579c8fa-53d7-41a8-b4cc-a03c712ebbb7",
"amount": 100,
"status": "captured",
"success": true,
"installments": 1,
"operation_type": "auth_and_capture",
"card": {
"id": "card_pD02Q6WtOTB7a3kE",
"first_six_digits": "400010",
"last_four_digits": "2224",
"brand": "Visa",
"holder_name": "Longbob Longsen",
"exp_month": 9,
"exp_year": 2019,
"status": "active",
"created_at": "2018-02-01T18:41:04Z",
"updated_at": "2018-02-01T18:41:04Z",
"billing_address": {
"street": "My Street",
"number": "456",
"zip_code": "K1C2N6",
"neighborhood": "Sesame Street",
"city": "Ottawa",
"state": "ON",
"country": "CA",
"line_1": "456, My Street, Sesame Street"
},
"type": "credit"
},
"created_at": "2018-02-01T18:41:04Z",
"updated_at": "2018-02-01T18:41:04Z",
"gateway_response": {
"code": "400",
"errors": [
{
"message": "Esta loja n??o possui um meio de pagamento configurado para a bandeira VR"
}
]
}
}
}
)
end

def successful_authorize_response
%(
{
Expand Down

0 comments on commit b1e0807

Please sign in to comment.