Skip to content

Commit

Permalink
CybersourceREST - Refund | Credit
Browse files Browse the repository at this point in the history
Description
-------------------------
This integration support the following payment operations:
- Refund
- Credit

Unit test
-------------------------
Finished in 37.39707 seconds.
5452 tests, 77126 assertions, 0 failures, 0 errors, 0 pendings, 0 omissions, 0 notifications
100% passed

Remote test
-------------------------
145.79 tests/s, 2062.35 assertions/s

Rubocop
-------------------------
760 files inspected, no offenses detected

GWI-471
  • Loading branch information
Luis committed Feb 16, 2023
1 parent 729026a commit 3eef976
Show file tree
Hide file tree
Showing 3 changed files with 123 additions and 5 deletions.
44 changes: 40 additions & 4 deletions lib/active_merchant/billing/gateways/cyber_source_rest.rb
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,17 @@ def authorize(money, payment, options = {}, capture = false)
post = build_auth_request(money, payment, options)
post[:processingInformation] = { capture: true } if capture

commit('/pts/v2/payments/', post)
commit('payments/', post)
end

def refund(money, options = {})
post = build_refund_request(money, options)
commit("payments/#{options[:order_id]}/refunds", post)
end

def credit(money, payment, options = {})
post = build_credit_request(money, payment, options)
commit('credits', post)
end

def supports_scrubbing?
Expand Down Expand Up @@ -71,6 +81,23 @@ def build_auth_request(amount, payment, options)
end.compact
end

def build_refund_request(amount, options)
{ clientReferenceInformation: {}, orderInformation: {} }.tap do |post|
add_code(post, options)
add_amount(post, amount)
end.compact
end

def build_credit_request(amount, payment, options)
{ clientReferenceInformation: {}, paymentInformation: {}, orderInformation: {} }.tap do |post|
add_code(post, options)
add_credit_card(post, payment)
add_amount(post, amount)
add_address(post, payment, options[:billing_address], options, :billTo)
add_merchant_description(post, options)
end.compact
end

def add_code(post, options)
return unless options[:order_id].present?

Expand Down Expand Up @@ -127,8 +154,17 @@ def add_address(post, payment_method, address, options, address_type)
}.compact
end

def add_merchant_description(post, options)
return unless options[:merchant_descriptor_name] || options[:merchant_descriptor_address1] || options[:merchant_descriptor_locality]

merchant = post[:merchantInformation][:merchantDescriptor] = {}
merchant[:name] = options[:merchant_descriptor_name] if options[:merchant_descriptor_name]
merchant[:address1] = options[:merchant_descriptor_address1] if options[:merchant_descriptor_address1]
merchant[:locality] = options[:merchant_descriptor_locality] if options[:merchant_descriptor_locality]
end

def url(action)
"#{(test? ? test_url : live_url)}#{action}"
"#{(test? ? test_url : live_url)}/pts/v2/#{action}"
end

def host
Expand Down Expand Up @@ -158,7 +194,7 @@ def commit(action, post)
end

def success_from(response)
response['status'] == 'AUTHORIZED'
%w(AUTHORIZED PENDING).include?(response['status'])
end

def message_from(response)
Expand All @@ -181,7 +217,7 @@ def get_http_signature(resource, digest, http_method = 'post', gmtdatetime = Tim
string_to_sign = {
host: host,
date: gmtdatetime,
"(request-target)": "#{http_method} #{resource}",
"(request-target)": "#{http_method} /pts/v2/#{resource}",
digest: digest,
"v-c-merchant-id": @options[:merchant_id]
}.map { |k, v| "#{k}: #{v}" }.join("\n").force_encoding(Encoding::UTF_8)
Expand Down
82 changes: 82 additions & 0 deletions test/remote/gateways/remote_cyber_source_rest_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,88 @@ def test_successful_purchase
assert_nil response.params['_links']['capture']
end

def test_successful_refund
purchase = @gateway.purchase(@amount, @visa_card, @options)
response = @gateway.refund(@amount, { order_id: purchase.authorization })

assert_success response
assert response.test?
assert_equal 'PENDING', response.message
assert response.params['id'].present?
assert response.params['_links']['void'].present?
end

def test_failure_refund
purchase = @gateway.purchase(@amount, @card_with_out_funds, @options)
response = @gateway.refund(@amount, { order_id: purchase.authorization })

assert_failure response
assert response.test?
assert_match %r{Declined - One or more fields in the request contains invalid data}, response.params['message']
assert_equal 'INVALID_DATA', response.params['reason']
end

def test_successful_less_than_the_payment_amount_refund
purchase = @gateway.purchase(@amount, @visa_card, @options)
response = @gateway.refund(@amount / 2, { order_id: purchase.authorization })

assert_success response
assert response.test?
assert_equal 'PENDING', response.message
assert response.params['id'].present?
assert response.params['_links']['void'].present?
end

def test_successful_more_than_the_payment_amount_refund
purchase = @gateway.purchase(@amount, @visa_card, @options)
response = @gateway.refund(@amount * 2, { order_id: purchase.authorization })

assert_success response
assert response.test?
assert_equal 'PENDING', response.message
assert response.params['id'].present?
assert response.params['_links']['void'].present?
end

def test_successful_double_refund_transactions
purchase = @gateway.purchase(@amount, @visa_card, @options)
response1 = @gateway.refund(@amount, { order_id: purchase.authorization })

assert_success response1
assert response1.test?
assert_equal 'PENDING', response1.message
assert response1.params['id'].present?
assert response1.params['_links']['void']

response2 = @gateway.refund(@amount, { order_id: purchase.authorization })
assert_success response2
assert response2.test?
assert_equal 'PENDING', response2.message
assert response2.params['id'].present?
assert response2.params['_links']['void']

assert_not_equal response1.params['_links']['void'], response2.params['_links']['void']
end

def test_successful_credit
response = @gateway.credit(@amount, @visa_card, @options)

assert_success response
assert response.test?
assert_equal 'PENDING', response.message
assert response.params['id'].present?
assert_nil response.params['_links']['capture']
end

def test_failure_credit
response = @gateway.credit(@amount, @card_with_out_funds, @options)

assert_failure response
assert response.test?
assert_match %r{Decline - Invalid account number}, response.message
assert_equal 'INVALID_ACCOUNT', response.error_code
end

def test_transcript_scrubbing
transcript = capture_transcript(@gateway) do
@gateway.authorize(@amount, @visa_card, @options)
Expand Down
2 changes: 1 addition & 1 deletion test/unit/gateways/cyber_source_rest_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ def test_add_shipping_address
end

def test_url_building
assert_equal "#{@gateway.class.test_url}/action", @gateway.send(:url, '/action')
assert_equal "#{@gateway.class.test_url}/pts/v2/action", @gateway.send(:url, 'action')
end

private
Expand Down

0 comments on commit 3eef976

Please sign in to comment.