Skip to content

Commit

Permalink
Merge branch 'master' into pessimistic_versioning
Browse files Browse the repository at this point in the history
* master:
  Allow nokogiri as low as 1.4.7
  Balanced: Adjust BalancedGateway::Error parent
  SecureNet: Allow some optional fields
  WebPay: add tests to modify currency unit in JPY from yen to sen.
  WebPay: modify refund method to support the new currency unit in JPY.
  WebPay: add unit tests to check the currency unit.
  WebPay: update a test API key.
  WebPay: modify the currency unit in JPY from yen (1) to sen (1/100).
  Update Stripe gateway to reflect current currency support
  added missing authorization_code param to response
  Moneris: Add verification_value support
  Credit deprecation test for litle.
  Litle: Deprecate credit method in favor of refund.
  Pass the primary response into the run method instead of tacking it on the end.
  Stripe: Make the actual refund response primary rather than the fee refund.
  Allow changing the primary response of a MultiResponse to the first one run.
  Firstdata E4: Include missing address information for AVS and CVV results.

Conflicts:
	activemerchant.gemspec
  • Loading branch information
David Underwood committed Aug 29, 2013
2 parents 4ddcc93 + 068b852 commit 24bf12d
Show file tree
Hide file tree
Showing 24 changed files with 296 additions and 42 deletions.
4 changes: 3 additions & 1 deletion CHANGELOG
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@
* PayU: Fix a major bug with status types [melari]
* SecureNet: Allow production transactions [duff]
* Stripe: Allow a card_not_present_fee to be specified [melari]

* Moneris: Add verification_value support [duff]
* SecureNet: Add INVOICENUM and INVOICEDESC optional fields [duff]
* Balanced: Make BalancedGateway::Error inherit from ActiveMerchantError [duff]

== Version 1.36.0 (August 2, 2013)

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ The [ActiveMerchant Wiki](http://github.com/Shopify/active_merchant/wikis) conta
* [SecurePayTech](http://www.securepaytech.com/) - NZ
* [SkipJack](http://www.skipjack.com/) - US, CA
* [Spreedly Core](https://spreedlycore.com/) - AD, AE, AT, AU, BD, BE, BG, BN, CA, CH, CY, CZ, DE, DK, EE, EG, ES, FI, FR, GB, GI, GR, HK, HU, ID, IE, IL, IM, IN, IS, IT, JO, KW, LB, LI, LK, LT, LU, LV, MC, MT, MU, MV, MX, MY, NL, NO, NZ, OM, PH, PL, PT, QA, RO, SA, SE, SG, SI, SK, SM, TR, TT, UM, US, VA, VN, ZA
* [Stripe](https://stripe.com/) - US
* [Stripe](https://stripe.com/) - US, CA, GB
* [TransFirst](http://www.transfirst.com/) - US
* [Transnational](http://www.tnbci.com/) - US
* [TrustCommerce](http://www.trustcommerce.com/) - US
Expand Down
2 changes: 1 addition & 1 deletion activemerchant.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ Gem::Specification.new do |s|
s.add_dependency('builder', '>= 2.1.2', '< 4.0.0')
s.add_dependency('json', '~> 1.8')
s.add_dependency('active_utils', '~> 2.0')
s.add_dependency('nokogiri', "~> 1.6")
s.add_dependency('nokogiri', "~> 1.4")

s.add_development_dependency('rake')
s.add_development_dependency('mocha', '~> 0.13.0')
Expand Down
2 changes: 1 addition & 1 deletion lib/active_merchant/billing/gateways/balanced.rb
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ class BalancedGateway < Gateway
self.display_name = 'Balanced'
self.money_format = :cents

class Error < StandardError
class Error < ActiveMerchant::ActiveMerchantError
attr_reader :response

def initialize(response, msg=nil)
Expand Down
17 changes: 14 additions & 3 deletions lib/active_merchant/billing/gateways/firstdata_e4.rb
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ def build_sale_or_authorization_request(money, credit_card_or_store_authorizatio
if credit_card_or_store_authorization.is_a? String
add_credit_card_token(xml, credit_card_or_store_authorization)
else
add_credit_card(xml, credit_card_or_store_authorization)
add_credit_card(xml, credit_card_or_store_authorization, options)
end

add_customer_data(xml, options)
Expand All @@ -138,7 +138,7 @@ def build_capture_or_credit_request(money, identification, options)
def build_store_request(credit_card, options)
xml = Builder::XmlMarkup.new

add_credit_card(xml, credit_card)
add_credit_card(xml, credit_card, options)
add_customer_data(xml, options)

xml.target!
Expand All @@ -164,12 +164,23 @@ def add_amount(xml, money)
xml.tag! "DollarAmount", amount(money)
end

def add_credit_card(xml, credit_card)
def add_credit_card(xml, credit_card, options)
xml.tag! "Card_Number", credit_card.number
xml.tag! "Expiry_Date", expdate(credit_card)
xml.tag! "CardHoldersName", credit_card.name
xml.tag! "CardType", credit_card.brand

add_credit_card_verification_strings(xml, credit_card, options)
end

def add_credit_card_verification_strings(xml, credit_card, options)
address = options[:billing_address] || options[:address]
if address
address_values = []
[:address1, :zip, :city, :state, :country].each { |part| address_values << address[part].to_s }
xml.tag! "VerificationStr1", address_values.join("|")
end

if credit_card.verification_value?
xml.tag! "CVD_Presence_Ind", "1"
xml.tag! "VerificationStr2", credit_card.verification_value
Expand Down
9 changes: 7 additions & 2 deletions lib/active_merchant/billing/gateways/litle.rb
Original file line number Diff line number Diff line change
Expand Up @@ -112,11 +112,16 @@ def void(identification, options = {})
end
end

def credit(money, identification_or_token, options = {})
to_pass = build_credit_request(money, identification_or_token, options)
def refund(money, authorization, options = {})
to_pass = build_credit_request(money, authorization, options)
build_response(:credit, @litle.credit(to_pass))
end

def credit(money, authorization, options = {})
deprecated CREDIT_DEPRECATION_MESSAGE
refund(money, authorization, options)
end

def store(creditcard_or_paypage_registration_id, options = {})
to_pass = create_token_hash(creditcard_or_paypage_registration_id, options)
build_response(:registerToken, @litle.register_token_request(to_pass), %w(000 801 802))
Expand Down
33 changes: 28 additions & 5 deletions lib/active_merchant/billing/gateways/moneris.rb
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ def add_payment_source(post, source)
else
post[:pan] = source.number
post[:expdate] = expdate(source)
post[:cvd_value] = source.verification_value if source.verification_value?
end
end

Expand Down Expand Up @@ -155,6 +156,7 @@ def commit(action, parameters = {})

Response.new(successful?(response), message_from(response[:message]), response,
:test => test?,
:cvv_result => response[:cvd_result_code].try(:last),
:authorization => authorization_from(response)
)
end
Expand Down Expand Up @@ -192,14 +194,35 @@ def post_data(action, parameters = {})
root = xml.add_element("request")
root.add_element("store_id").text = options[:login]
root.add_element("api_token").text = options[:password]
transaction = root.add_element(action)
root.add_element(transaction_element(action, parameters))

xml.to_s
end

def transaction_element(action, parameters)
transaction = REXML::Element.new(action)

# Must add the elements in the correct order
actions[action].each do |key|
transaction.add_element(key.to_s).text = parameters[key] unless parameters[key].blank?
if key == :cvd_info
transaction.add_element(cvd_element(parameters[:cvd_value]))
else
transaction.add_element(key.to_s).text = parameters[key] unless parameters[key].blank?
end
end

xml.to_s
transaction
end

def cvd_element(cvd_value)
element = REXML::Element.new('cvd_info')
if cvd_value
element.add_element('cvd_indicator').text = "1"
element.add_element('cvd_value').text = cvd_value
else
element.add_element('cvd_indicator').text = "0"
end
element
end

def message_from(message)
Expand All @@ -219,8 +242,8 @@ def normalize(field)

def actions
{
"purchase" => [:order_id, :cust_id, :amount, :pan, :expdate, :crypt_type],
"preauth" => [:order_id, :cust_id, :amount, :pan, :expdate, :crypt_type],
"purchase" => [:order_id, :cust_id, :amount, :pan, :expdate, :crypt_type, :cvd_info],
"preauth" => [:order_id, :cust_id, :amount, :pan, :expdate, :crypt_type, :cvd_info],
"command" => [:order_id],
"refund" => [:order_id, :amount, :txn_number, :crypt_type],
"indrefund" => [:order_id, :cust_id, :amount, :pan, :expdate, :crypt_type],
Expand Down
5 changes: 3 additions & 2 deletions lib/active_merchant/billing/gateways/secure_net.rb
Original file line number Diff line number Diff line change
Expand Up @@ -182,8 +182,9 @@ def add_address(xml, creditcard, options)
end

def add_invoice(xml, options)
xml.tag! 'INVOICEDESC', options[:description]
xml.tag! 'INVOICENUM', 'inv-8'
xml.tag! 'NOTE', options[:description] if options[:description]
xml.tag! 'INVOICEDESC', options[:invoice_description] if options[:invoice_description]
xml.tag! 'INVOICENUM', options[:invoice_number] if options[:invoice_number]
end

def add_merchant_key(xml, options)
Expand Down
4 changes: 2 additions & 2 deletions lib/active_merchant/billing/gateways/stripe.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ class StripeGateway < Gateway
'unchecked' => 'P'
}

self.supported_countries = ['US', 'CA']
self.supported_countries = ['US', 'CA', 'GB']
self.default_currency = 'USD'
self.money_format = :cents
self.supported_cardtypes = [:visa, :master, :american_express, :discover, :jcb, :diners_club]
Expand Down Expand Up @@ -71,7 +71,7 @@ def refund(money, identification, options = {})
post = {:amount => amount(money)}
commit_options = generate_meta(options)

MultiResponse.run do |r|
MultiResponse.run(:first) do |r|
r.process { commit(:post, "charges/#{CGI.escape(identification)}/refund", post, commit_options) }

return r unless options[:refund_fee_amount]
Expand Down
23 changes: 23 additions & 0 deletions lib/active_merchant/billing/gateways/webpay.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,33 @@ def capture(money, credit_card, options = {})
raise NotImplementedError.new
end

def refund(money, identification, options = {})
post = {:amount => localized_amount(money)}
commit_options = generate_meta(options)

MultiResponse.run do |r|
r.process { commit(:post, "charges/#{CGI.escape(identification)}/refund", post, commit_options) }

return r unless options[:refund_fee_amount]

r.process { fetch_application_fees(identification, commit_options) }
r.process { refund_application_fee(options[:refund_fee_amount], application_fee_from_response(r), commit_options) }
end
end

def refund_fee(identification, options, meta)
raise NotImplementedError.new
end

def localized_amount(money, currency = self.default_currency)
non_fractional_currency?(currency) ? (amount(money).to_f / 100).floor : amount(money)
end

def add_amount(post, money, options)
post[:currency] = (options[:currency] || currency(money)).downcase
post[:amount] = localized_amount(money, post[:currency].upcase)
end

def json_error(raw_response)
msg = 'Invalid response received from the WebPay API. Please contact support@webpay.jp if you continue to receive this message.'
msg += " (The raw response returned by the API was #{raw_response.inspect})"
Expand Down
14 changes: 11 additions & 3 deletions lib/active_merchant/billing/response.rb
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,18 @@ def initialize(success, message, params = {}, options = {})
end

class MultiResponse < Response
def self.run(&block)
new.tap(&block)
def self.run(primary_response = :last, &block)
response = new.tap(&block)
response.primary_response = primary_response
response
end

attr_reader :responses
attr_writer :primary_response

def initialize
@responses = []
@primary_response = :last
end

def process
Expand All @@ -65,10 +69,14 @@ def success?
@responses.all?{|r| r.success?}
end

def primary_response
success? && @primary_response == :first ? @responses.first : @responses.last
end

%w(params message test authorization avs_result cvv_result test? fraud_review?).each do |m|
class_eval %(
def #{m}
(@responses.empty? ? nil : @responses.last.#{m})
(@responses.empty? ? nil : primary_response.#{m})
end
)
end
Expand Down
2 changes: 1 addition & 1 deletion test/fixtures.yml
Original file line number Diff line number Diff line change
Expand Up @@ -626,7 +626,7 @@ vindicia:
password: PASSWORD

webpay:
login: "vtUQeOtUnYr7PGCLQ96Ul4zqpDUO4sOE"
login: "test_secret_eHn4TTgsGguBcW764a2KA8Yd"

# Working test credentials, no need to replace
wirecard:
Expand Down
2 changes: 2 additions & 0 deletions test/remote/gateways/remote_authorize_net_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ def test_bad_login

assert_equal Response, response.class
assert_equal ["action",
"authorization_code",
"avs_result_code",
"card_code",
"response_code",
Expand All @@ -128,6 +129,7 @@ def test_using_test_request

assert_equal Response, response.class
assert_equal ["action",
"authorization_code",
"avs_result_code",
"card_code",
"response_code",
Expand Down
8 changes: 8 additions & 0 deletions test/remote/gateways/remote_firstdata_e4_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -78,4 +78,12 @@ def test_invalid_login
assert_match /Unauthorized Request/, response.message
assert_failure response
end

def test_response_contains_cvv_and_avs_results
response = @gateway.purchase(@amount, @credit_card, @options)
assert_success response
assert_equal 'M', response.cvv_result["code"]
assert_equal '1', response.avs_result["code"]
end

end
8 changes: 4 additions & 4 deletions test/remote/gateways/remote_litle_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ def test_unsuccessful_purchase
assert_equal 'Insufficient Funds', response.message
end

def test_authorization_capture_credit_void
def test_authorization_capture_refund_void
#Auth
assert auth_response = @gateway.authorize(10010, @credit_card1, @options)

Expand All @@ -102,7 +102,7 @@ def test_authorization_capture_credit_void

#Credit against the Capture
capture_litle_txn_id = capture_response.params['litleOnlineResponse']['captureResponse']['litleTxnId']
assert credit_response = @gateway.credit(10010, capture_litle_txn_id)
assert credit_response = @gateway.refund(10010, capture_litle_txn_id)
assert_success credit_response
assert_equal 'Approved', credit_response.message

Expand All @@ -119,8 +119,8 @@ def test_capture_unsuccessful
assert_equal 'No transaction found with specified litleTxnId', capture_response.message
end

def test_credit_unsuccessful
assert credit_response = @gateway.credit(10010, 123456789012345360)
def test_refund_unsuccessful
assert credit_response = @gateway.refund(10010, 123456789012345360)
assert_failure credit_response
assert_equal 'No transaction found with specified litleTxnId', credit_response.message
end
Expand Down
18 changes: 15 additions & 3 deletions test/remote/gateways/remote_moneris_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,12 @@ def test_successful_authorization_and_void
assert_success void
end

def test_successful_purchase_and_credit
def test_successful_purchase_and_refund
purchase = @gateway.purchase(@amount, @credit_card, @options)
assert_success purchase

credit = @gateway.credit(@amount, purchase.authorization)
assert_success credit
refund = @gateway.refund(@amount, purchase.authorization)
assert_success refund
end

def test_failed_purchase_from_error
Expand Down Expand Up @@ -108,4 +108,16 @@ def test_failed_authorization_with_vault
assert_failure response
end

def test_cvv_match
assert response = @gateway.purchase(1039, @credit_card, @options)
assert_success response
assert_equal({'code' => 'M', 'message' => 'Match'}, response.cvv_result)
end

def test_cvv_no_match
assert response = @gateway.purchase(1053, @credit_card, @options)
assert_success response
assert_equal({'code' => 'N', 'message' => 'No Match'}, response.cvv_result)
end

end
Loading

0 comments on commit 24bf12d

Please sign in to comment.