diff --git a/.gitignore b/.gitignore
index 657f2298ada..806ae574dd2 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,3 +6,4 @@ pkg
Gemfile.lock
Gemfile*.lock
.rbx/
+*.gem
\ No newline at end of file
diff --git a/CHANGELOG b/CHANGELOG
index 4185d018aa6..ab25c8fb8dd 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,5 +1,75 @@
= ActiveMerchant CHANGELOG
+* Balanced: Add support for appears_on_statement_as [duff]
+* Authorize.Net: Make already actioned responses failures [odorcicd]
+* Add Payex gateway [atomgiant]
+* Paymill: Fix authorizations [duff]
+* Braintree Blue: Allow specifying the credit card token [ntalbott]
+* Braintree Blue: Allow specifying the customer id [ntalbott]
+* Braintree Blue: Scrub invalid emails and zips [ntalbott]
+* Braintree Blue: Return :credit_card_token as a top level param [ntalbott]
+* Braintree Blue: Allow unstoring just a credit card [ntalbott]
+* Braintree Blue: #store adds cards to existing customers [ntalbott]
+* USA ePay Advanced: Fix check handling [nearapogee]
+* USA ePay Advanced: Fix credit card expiration handling [nearapogee]
+* USA ePay Advanced: Fix handling of custom transaction responses for single items [nearapogee]
+* USA ePay Advanced: Fix capture amount [nearapogee]
+* NAB Transact: Fix merchant descriptor with capture/refund requests [nagash]
+* Braintree Blue: Add custom_fields & device_data parameters [parallel588]
+* Webpay: Add authorize & capture [keikubo]
+* MerchantWarrior: Pass description [duff]
+* Stripe: Separate email from description [duff]
+* Add Payscout gateway [llopez]
+* Merchant Warrior: Use billing_address [duff]
+* Add SoEasyPay gateway [ir-soeasycorp]
+* Bogus: Add check support [npverni]
+* Payflow: Add Check support [crazyivan]
+* eWay Rapid: Upgrade to 3.1 [atomgiant]
+
+== Version 1.42.2 (November 13th, 2013)
+
+* Renew public certificate
+
+== Version 1.42.1 (November 13th, 2013)
+
+* Signed version of 1.42.0
+
+== Version 1.42.0 (November 13th, 2013)
+
+* Fix NoMethodError "tr" for params with dash [TimothyKlim]
+* Authorize.Net: Add cardholder authentication options (CAVV) support [structure]
+* CardStreamModern: Added better checks on inputs from the gateway [ExxKA]
+* Stripe: Send :ip to the gateway instead of :browser_ip [f3ndot]
+* Wirecard Page: new offsite gateway [mbretter]
+* Mercury: Add support for requesting a token [kcdragon]
+* Add App55 gateway [ianbutler55]
+* UsaEpayTransaction: Support for split payments [GBH]
+* Add Swipe Checkout gateway [matt-optimizerhq]
+* Spreedly Core: Allow overriding the gateway token when running a transaction [hoenth]
+* Spreedly Core: Add order_id [hoenth]
+* Spreedly Core: Allow store without retain [hoenth]
+* Stripe: Support multiple cards on account [pierre]
+* Stripe: Add card_id parameter to unstore call [pierre]
+* Remove usage of `uname -a` [ntalbott]
+* Litle: Allow easier access to the response code [duff]
+* Stripe: Add the option to pass a version header [odorcicd]
+* Elavon: Update supported countries [duff]
+* Add Raven PacNet gateway [llopez]
+* BitPay: Fix BitPay issues and implement Notification#acknowledge [odorcicd]
+
+== Version 1.41.0 (October 24th, 2013)
+
+* Stripe: Payments won't fail when specifying a customer with a creditcard number [melari]
+* Add Conekta gateway [leofischer]
+* Wirecard: Add support for void and refund [duff]
+* Orbital: Mandatory field fix [juicedM3, jduff]
+
+== Version 1.40.0 (October 18th, 2013)
+
+* Paymill: Revert Add support for specifying the :customer [melari]
+* Quickpay: Make v7 of the API default [kvs]
+* Bitpay: Add return [tahnok]
+
== Version 1.39.2 (October 10th, 2013)
* Eway Rapid: Fix a bug with access codes that have equal signs in them [odorcic]
@@ -1249,4 +1319,3 @@ value [jduff]
* Credit card validation methods as static methods of the credit card object
== PlanetArgon fork for integrating Merchant eSolutions gateway
-
diff --git a/CONTRIBUTORS b/CONTRIBUTORS
index c3fd6412c43..d5adc5543c2 100644
--- a/CONTRIBUTORS
+++ b/CONTRIBUTORS
@@ -420,3 +420,31 @@ MoneyMovers (September 2013)
Be2Bill (September 2013)
* Michaël Hoste (MichaelHoste)
+
+Conekta (October 2013)
+
+* Leo Fischer (leofischer)
+
+App55 (November 2013)
+
+* (ianbutler55)
+
+Swipe Checkout (November 2013)
+
+* (matt-optimizerhq)
+
+Raven PacNet (November 2013)
+
+* Luis Lopez (llopez)
+
+Payex (November 2013)
+
+* Tom Davies (atomgiant)
+
+Payscout (December 2013)
+
+* Luis Lopez (llopez)
+
+SoEasyPay (December 2013)
+
+* Ivan Radovanovic (ir-soeasycorp)
diff --git a/README.md b/README.md
index 420f6573c1b..b4d8372fe89 100644
--- a/README.md
+++ b/README.md
@@ -81,6 +81,7 @@ For more in-depth documentation and tutorials, see [GettingStarted.md](GettingSt
The [ActiveMerchant Wiki](http://github.com/Shopify/active_merchant/wikis) contains a [table of features supported by each gateway](http://github.com/Shopify/active_merchant/wikis/gatewayfeaturematrix).
+* [App55](https://www.app55.com/) - AU, BR, CA, CH, CL, CN, CO, CZ, DK, EU, GB, HK, HU, ID, IS, JP, KE, KR, MX, MY, NO, NZ, PH, PL, TH, TW, US, VN, ZA
* [Authorize.Net CIM](http://www.authorize.net/) - US
* [Authorize.Net](http://www.authorize.net/) - US, CA, GB
* [Balanced](https://www.balancedpayments.com/) - US
@@ -94,6 +95,7 @@ The [ActiveMerchant Wiki](http://github.com/Shopify/active_merchant/wikis) conta
* [CardSave](http://www.cardsave.net/) - GB
* [CardStream](http://www.cardstream.com/) - GB
* [CertoDirect](http://www.certodirect.com/) - BE, BG, CZ, DK, DE, EE, IE, EL, ES, FR, IT, CY, LV, LT, LU, HU, MT, NL, AT, PL, PT, RO, SI, SK, FI, SE, GB
+* [Conekta](https://conekta.io) - MX
* [CyberSource](http://www.cybersource.com) - US, BR, CA, CN, DK, FI, FR, DE, JP, MX, NO, SE, GB, SG
* [DataCash](http://www.datacash.com/) - GB
* [Efsnet](http://www.concordefsnet.com/) - US
@@ -101,7 +103,7 @@ The [ActiveMerchant Wiki](http://github.com/Shopify/active_merchant/wikis) conta
* [ePay](http://epay.dk/) - DK, SE, NO
* [EVO Canada](http://www.evocanada.com/) - CA
* [eWAY](http://www.eway.com.au/) - AU, NZ, GB
-* [eWAY Rapid 3.0](http://www.eway.com.au/) - AU
+* [eWAY Rapid 3.1](http://www.eway.com.au/) - AU
* [E-xact](http://www.e-xact.com) - CA, US
* [Fat Zebra](https://www.fatzebra.com.au/) - AU
* [Federated Canada](http://www.federatedcanada.com/) - CA
@@ -142,6 +144,7 @@ The [ActiveMerchant Wiki](http://github.com/Shopify/active_merchant/wikis) conta
* [PayJunction](http://www.payjunction.com/) - US
* [PaySecure](http://www.commsecure.com.au/paysecure.shtml) - AU
* [Paybox Direct](http://www.paybox.com/) - FR
+* [Payex](http://payex.com/) - DK, NO, SE
* [PaymentExpress](http://www.paymentexpress.com/) - AU, CA, DE, ES, FR, GB, HK, IE, MY, NL, NZ, SG, US, ZA
* [PAYMILL](https://paymill.com) - AD, AT, BE, BG, CH, CY, CZ, DE, DK, EE, ES, FI, FO, FR, GB, GI, GR, HU, IE, IL, IS, IT, LI, LT, LU, LV, MT, NL, NO, PL, PT, RO, SE, SI, SK, TR, VA
* [PayPal Express Checkout](https://www.paypal.com/webapps/mpp/express-checkout) - US, CA, SG, AU
@@ -151,6 +154,7 @@ The [ActiveMerchant Wiki](http://github.com/Shopify/active_merchant/wikis) conta
* [PayPal Payments Pro (UK)](https://www.paypal.com/uk/webapps/mpp/pro) - GB
* [PayPal Website Payments Pro (CA)](https://www.paypal.com/cgi-bin/webscr?cmd=_wp-pro-overview-outside) - CA
* [PayPal Express Checkout for Digital Goods](https://www.x.com/community/ppx/xspaces/digital_goods) - AU, CA, CN, FI, GB, ID, IN, IT, MY, NO, NZ, PH, PL, SE, SG, TH, VN
+* [Payscout](http://www.payscout.com/) - US
* [Paystation](http://paystation.co.nz) - NZ
* [Pay Way](http://www.payway.com.au) - AU
* [Pin](http://www.pin.net.au/) - AU
@@ -160,6 +164,7 @@ The [ActiveMerchant Wiki](http://github.com/Shopify/active_merchant/wikis) conta
* [QuickBooks Merchant Services](http://payments.intuit.com/) - US
* [Quantum Gateway](http://www.quantumgateway.com) - US
* [Quickpay](http://quickpay.dk/) - DK, SE
+* [Raven PacNet](http://www.pacnetservices.com/) - US
* [Realex](http://www.realexpayments.com/) - IE, GB, FR, BE, NL, LU, IT
* [Redsys](http://www.redsys.es/) - ES
* [SagePay](http://www.sagepay.com) - GB, IE
@@ -170,8 +175,10 @@ The [ActiveMerchant Wiki](http://github.com/Shopify/active_merchant/wikis) conta
* [SecurePay](http://www.securepay.com/) - US, CA, GB, AU
* [SecurePayTech](http://www.securepaytech.com/) - NZ
* [SkipJack](http://www.skipjack.com/) - US, CA
+* [SoEasyPay](http://www.soeasypay.com/) - US, CA, AT, BE, BG, HR, CY, CZ, DK, EE, FI, FR, DE, GR, HU, IE, IT, LV, LT, LU, MT, NL, PL, PT, RO, SK, SI, ES, SE, GB, IS, NO, CH
* [Spreedly](https://spreedly.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, CA, GB, AU, IE, FR, NL, BE, DE, ES
+* [Swipe](https://www.swipehq.com/checkout) - CA, NZ
* [TransFirst](http://www.transfirst.com/) - US
* [NELiX TransaX](https://www.nelixtransax.com/) - US
* [Transnational](http://www.tnbci.com/) - US
diff --git a/RELEASING b/RELEASING
index a22f2819530..cae01fe9c04 100644
--- a/RELEASING
+++ b/RELEASING
@@ -4,12 +4,5 @@ releasing Active Merchant
2. Check the Semantic Versioning page for info on how to version the new release: http://semver.org
3. Update the version of Active Merchant in lib/active_merchant/version.rb and in activemerchant.gemspec
4. Add a CHANGELOG entry for the new release with the date
-5. Commit the changes with a commit message like "Packaging for release X.Y.Z"
-6. Tag the release with the version (Leave REV blank for HEAD or provide a SHA)
- $ git tag vX.Y.Z REV
-7. Push out the changes
- $ git push
-8. Push out the tags
- $ git push --tags
-9. Publish the Gem to gemcutter
- $ rake release GEM_PRIVATE_KEY=/path/to/private/key
\ No newline at end of file
+5. Release the gem to rubygems
+ $ GEM_PRIVATE_KEY=/path/to/private/key bundle exec rake release
\ No newline at end of file
diff --git a/Rakefile b/Rakefile
index 5124db49d7f..fa64d35f8ea 100644
--- a/Rakefile
+++ b/Rakefile
@@ -1,4 +1,5 @@
$:.unshift File.expand_path('../lib', __FILE__)
+require 'active_merchant/version'
begin
require 'bundler'
@@ -10,14 +11,29 @@ end
require 'rake'
require 'rake/testtask'
-require 'rubygems/package_task'
require 'support/gateway_support'
require 'support/ssl_verify'
require 'support/outbound_hosts'
+task :gem => :build
+task :build do
+ raise "Please set a private key to sign the gem" unless ENV['GEM_PRIVATE_KEY']
+ system "gem build activemerchant.gemspec"
+end
+
+task :install => :build do
+ system "gem install activemerchant-#{ActiveMerchant::VERSION}.gem"
+end
+
+task :release => :build do
+ system "git tag -a v#{ActiveMerchant::VERSION} -m 'Tagging #{ActiveMerchant::VERSION}'"
+ system "git push --tags"
+ system "gem push activemerchant-#{ActiveMerchant::VERSION}.gem"
+ system "rm activemerchant-#{ActiveMerchant::VERSION}.gem"
+end
+
desc "Run the unit test suite"
task :default => 'test:units'
-
task :test => 'test:units'
namespace :test do
@@ -35,28 +51,6 @@ namespace :test do
t.libs << 'test'
t.verbose = true
end
-
-end
-
-desc "Delete tar.gz / zip"
-task :cleanup => [ :clobber_package ]
-
-spec = eval(File.read('activemerchant.gemspec'))
-
-Gem::PackageTask.new(spec) do |p|
- p.gem_spec = spec
- p.need_tar = true
- p.need_zip = true
-end
-
-desc "Release the gems and docs to RubyForge"
-task :release => [ 'gemcutter:publish' ]
-
-namespace :gemcutter do
- desc "Publish to gemcutter"
- task :publish => :package do
- sh "gem push pkg/activemerchant-#{ActiveMerchant::VERSION}.gem"
- end
end
namespace :gateways do
diff --git a/activemerchant.gemspec b/activemerchant.gemspec
index 152c2bca3d1..6d31a5299fc 100644
--- a/activemerchant.gemspec
+++ b/activemerchant.gemspec
@@ -21,7 +21,7 @@ Gem::Specification.new do |s|
s.add_dependency('activesupport', '>= 2.3.14', '< 5.0.0')
s.add_dependency('i18n', '~> 0.5')
- s.add_dependency('money', '< 6.0.0')
+ s.add_dependency('money', '< 7.0.0')
s.add_dependency('builder', '>= 2.1.2', '< 4.0.0')
s.add_dependency('json', '~> 1.7')
s.add_dependency('active_utils', '~> 2.0', '>= 2.0.1')
diff --git a/gem-public_cert.pem b/gem-public_cert.pem
index c2588d5c296..7d87bf88dbd 100644
--- a/gem-public_cert.pem
+++ b/gem-public_cert.pem
@@ -1,7 +1,7 @@
-----BEGIN CERTIFICATE-----
-MIIDNjCCAh6gAwIBAgIBADANBgkqhkiG9w0BAQUFADBBMRMwEQYDVQQDDApjb2R5
+MIIDeDCCAmCgAwIBAgIBATANBgkqhkiG9w0BAQUFADBBMRMwEQYDVQQDDApjb2R5
ZmF1c2VyMRUwEwYKCZImiZPyLGQBGRYFZ21haWwxEzARBgoJkiaJk/IsZAEZFgNj
-b20wHhcNMDcwMjIyMTcyMTI3WhcNMDgwMjIyMTcyMTI3WjBBMRMwEQYDVQQDDApj
+b20wHhcNMTMxMTEzMTk1NjE2WhcNMTQxMTEzMTk1NjE2WjBBMRMwEQYDVQQDDApj
b2R5ZmF1c2VyMRUwEwYKCZImiZPyLGQBGRYFZ21haWwxEzARBgoJkiaJk/IsZAEZ
FgNjb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC6T4Iqt5iWvAlU
iXI6L8UO0URQhIC65X/gJ9hL/x4lwSl/ckVm/R/bPrJGmifT+YooFv824N3y/TIX
@@ -9,12 +9,13 @@ iXI6L8UO0URQhIC65X/gJ9hL/x4lwSl/ckVm/R/bPrJGmifT+YooFv824N3y/TIX
O3wqEjvW2L6VMozVfK1MfjL9IGgy0rCnl+2g4Gh4jDDpkLfnMG5CWI6cTCf3C1ye
ytOpWgi0XpOEy8nQWcFmt/KCQ/kFfzBo4QxqJi54b80842EyvzWT9OB7Oew/CXZG
F2yIHtiYxonz6N09vvSzq4CvEuisoUFLKZnktndxMEBKwJU3XeSHAbuS7ix40OKO
-WKuI54fHAgMBAAGjOTA3MAkGA1UdEwQCMAAwCwYDVR0PBAQDAgSwMB0GA1UdDgQW
-BBR9QQpefI3oDCAxiqJW/3Gg6jI6qjANBgkqhkiG9w0BAQUFAAOCAQEAs0lX26O+
-HpyMp7WL+SgZuM8k76AjfOHuKajl2GEn3S8pWYGpsa0xu07HtehJhKLiavrfUYeE
-qlFtyYMUyOh6/1S2vfkH6VqjX7mWjoi7XKHW/99fkMS40B5SbN+ypAUst+6c5R84
-w390mjtLHpdDE6WQYhS6bFvBN53vK6jG3DLyCJc0K9uMQ7gdHWoxq7RnG92ncQpT
-ThpRA+fky5Xt2Q63YJDnJpkYAz79QIama1enSnd4jslKzSl89JS2luq/zioPe/Us
-hbyalWR1+HrhgPoSPq7nk+s2FQUBJ9UZFK1lgMzho/4fZgzJwbu+cO8SNuaLS/bj
-hPaSTyVU0yCSnw==
+WKuI54fHAgMBAAGjezB5MAkGA1UdEwQCMAAwCwYDVR0PBAQDAgSwMB0GA1UdDgQW
+BBR9QQpefI3oDCAxiqJW/3Gg6jI6qjAfBgNVHREEGDAWgRRjb2R5ZmF1c2VyQGdt
+YWlsLmNvbTAfBgNVHRIEGDAWgRRjb2R5ZmF1c2VyQGdtYWlsLmNvbTANBgkqhkiG
+9w0BAQUFAAOCAQEAYJgMj+RlvKSOcks29P76WE+Lexvq3eZBDxxgFHatACdq5Fis
+MUEGiiHeLkR1KRTkvkXCos6CtZVUBVUsftueHmKA7adO2yhrjv4YhPTb/WZxWmQC
+L59lMhnp9UcFJ0H7TkAiU1TvvXewdQPseX8Ayl0zRwD70RfhGh0LfFsKN0JGR4ZS
+yZvtu7hS26h9KwIyo5N3nw7cKSLzT7KsV+s1C+rTjVCb3/JJA9yOe/SCj/Xyc+JW
+ZJB9YPQZG+vWBdDSca3sUMtvFxpLUFwdKF5APSPOVnhbFJ3vSXY1ulP/R6XW9vnw
+6kkQi2fHhU20ugMzp881Eixr+TjC0RvUerLG7g==
-----END CERTIFICATE-----
diff --git a/generators/integration/templates/notification.rb b/generators/integration/templates/notification.rb
index 72416fbc6cf..4e66fb2f500 100644
--- a/generators/integration/templates/notification.rb
+++ b/generators/integration/templates/notification.rb
@@ -90,8 +90,8 @@ def acknowledge(authcode = nil)
def parse(post)
@raw = post.to_s
for line in @raw.split('&')
- key, value = *line.scan( %r{^([A-Za-z0-9_.]+)\=(.*)$} ).flatten
- params[key] = CGI.unescape(value)
+ key, value = *line.scan( %r{^([A-Za-z0-9_.-]+)\=(.*)$} ).flatten
+ params[key] = CGI.unescape(value.to_s) if key.present?
end
end
end
diff --git a/lib/active_merchant/billing/base.rb b/lib/active_merchant/billing/base.rb
index 719480c5f6c..f059de6b705 100644
--- a/lib/active_merchant/billing/base.rb
+++ b/lib/active_merchant/billing/base.rb
@@ -31,8 +31,15 @@ def self.mode=(mode)
#
# ActiveMerchant::Billing::Base.gateway('moneris').new
def self.gateway(name)
- raise NameError if (name_str = name.to_s.downcase).blank?
- Billing.const_get("#{name_str}_gateway".camelize)
+ name_str = name.to_s.strip.downcase
+
+ raise(ArgumentError, 'A gateway provider must be specified') if name_str.blank?
+
+ begin
+ Billing.const_get("#{name_str}_gateway".camelize)
+ rescue
+ raise ArgumentError, "The specified gateway is not valid (#{name_str})"
+ end
end
# Return the matching integration module
diff --git a/lib/active_merchant/billing/credit_card_methods.rb b/lib/active_merchant/billing/credit_card_methods.rb
index fef4bf16c52..a7801819fcd 100644
--- a/lib/active_merchant/billing/credit_card_methods.rb
+++ b/lib/active_merchant/billing/credit_card_methods.rb
@@ -126,7 +126,7 @@ def valid_test_mode_card_number?(number) #:nodoc:
%w[1 2 3 success failure error].include?(number.to_s)
end
- # Checks the validity of a card number by use of the the Luhn Algorithm.
+ # Checks the validity of a card number by use of the Luhn Algorithm.
# Please see http://en.wikipedia.org/wiki/Luhn_algorithm for details.
def valid_checksum?(number) #:nodoc:
sum = 0
diff --git a/lib/active_merchant/billing/gateway.rb b/lib/active_merchant/billing/gateway.rb
index 97b31208db5..39826a2d7ce 100644
--- a/lib/active_merchant/billing/gateway.rb
+++ b/lib/active_merchant/billing/gateway.rb
@@ -62,7 +62,7 @@ class Gateway
include Utils
DEBIT_CARDS = [ :switch, :solo ]
- CURRENCIES_WITHOUT_FRACTIONS = [ 'JPY', 'HUF', 'TWD' ]
+ CURRENCIES_WITHOUT_FRACTIONS = [ 'JPY', 'HUF', 'TWD', 'ISK' ]
CREDIT_DEPRECATION_MESSAGE = "Support for using credit to refund existing transactions is deprecated and will be removed from a future release of ActiveMerchant. Please use the refund method instead."
cattr_reader :implementations
@@ -161,7 +161,14 @@ def amount(money)
def localized_amount(money, currency)
amount = amount(money)
- non_fractional_currency?(currency) ? amount.split('.').first : amount
+
+ return amount unless non_fractional_currency?(currency)
+
+ if self.money_format == :cents
+ sprintf("%.0f", amount.to_f / 100)
+ else
+ amount.split('.').first
+ end
end
def non_fractional_currency?(currency)
diff --git a/lib/active_merchant/billing/gateways/app55.rb b/lib/active_merchant/billing/gateways/app55.rb
new file mode 100644
index 00000000000..b775dcb8197
--- /dev/null
+++ b/lib/active_merchant/billing/gateways/app55.rb
@@ -0,0 +1,185 @@
+module ActiveMerchant #:nodoc:
+ module Billing #:nodoc:
+ class App55Gateway < Gateway
+ self.test_url = 'https://sandbox.app55.com/v1/'
+ self.live_url = 'https://api.app55.com/v1/'
+
+ self.supported_countries = ['AU', 'BR', 'CA', 'CH', 'CL', 'CN', 'CO', 'CZ', 'DK', 'EU', 'GB', 'HK', 'HU', 'ID', 'IS', 'JP', 'KE', 'KR', 'MX', 'MY', 'NO', 'NZ', 'PH', 'PL', 'TH', 'TW', 'US', 'VN', 'ZA']
+ self.supported_cardtypes = [:visa, :master, :american_express, :jcb, :maestro, :solo]
+ self.default_currency = 'UKP'
+ self.money_format = :dollars
+ self.homepage_url = 'https://www.app55.com/'
+ self.display_name = 'App55'
+
+ # Create gateway
+ #
+ # options:
+ # :api_key - merchants App55 API Key
+ # :api_secret - merchants App55 Secret Key
+ def initialize(options = {})
+ requires!(options, :api_key, :api_secret)
+ @api_key = options[:api_key]
+ @api_secret = options[:api_secret]
+ super
+ end
+
+ # Make a purchase (authorize and commit)
+ #
+ # money - The monetary amount of the transaction in cents.
+ # payment_method - The CreditCard or the App55 card token.
+ # options - A standard ActiveMerchant options hash
+ def purchase(money, payment_method, options = {})
+ authorize(money, payment_method, options.merge(commit: true))
+ end
+
+ # Authorize a transaction.
+ #
+ # money - The monetary amount of the transaction in cents.
+ # payment_method - The CreditCard or the App55 card token.
+ # options - A standard ActiveMerchant options hash
+ def authorize(money, payment_method, options = {})
+ post = {}
+ add_creditcard(post, payment_method, options)
+ add_transaction(post, money, options)
+
+ commit(:post, 'transaction', post)
+ end
+
+ # Commit a pre-authorized transaction.
+ #
+ # money - The monetary amount of the transaction in cents.
+ # authorization - The App55 transaction id string.
+ # options - A standard ActiveMerchant options hash
+ def capture(money, authorization, options = {})
+ commit(:post, "transaction/#{authorization}")
+ end
+
+ private
+
+ def add_customer_data(post, options)
+ metadata_options = [:description, :browser_ip, :user_agent, :referrer]
+ post.update(options.slice(*metadata_options))
+ end
+
+ def add_creditcard(post, creditcard, options)
+ card = {}
+ card[:number] = creditcard.number
+ card[:expiry] = ("%02d". % creditcard.month) + '/' + creditcard.year.to_s
+ card[:security_code] = creditcard.verification_value if creditcard.verification_value?
+ card[:holder_name] = creditcard.name if creditcard.name
+ add_address(card, options)
+ post[:card] = card
+ end
+
+ def add_address(card, options)
+ return unless card && card.kind_of?(Hash)
+ address_hash = {}
+ if address = (options[:billing_address] || options[:address])
+ address_hash[:street] = address[:address1] if address[:address1]
+ address_hash[:street2] = address[:address2] if address[:address2]
+ address_hash[:country] = address[:country] if address[:country]
+ address_hash[:postal_code] = address[:zip] if address[:zip]
+ address_hash[:city] = address[:city] if address[:city]
+ card[:address] = address_hash
+ end
+ end
+
+ def add_transaction(post, money, options)
+ transaction = {}
+ add_amount(transaction, money, options)
+ transaction[:description] = (options[:description] || options[:email])
+ transaction[:commit] = options[:commit]
+ post[:transaction] = transaction
+ end
+
+ def add_amount(obj, money, options)
+ obj[:amount] = amount(money)
+ obj[:currency] = (options[:currency] || currency(money))
+ end
+
+ def parse(body)
+ JSON.parse(body)
+ rescue JSON::ParserError
+ json_error(raw_response)
+ end
+
+ def commit(method, resource, parameters=nil, meta={})
+ success = false
+ begin
+ raw_response = ssl_request(
+ method,
+ url(resource),
+ post_data(parameters),
+ headers
+ )
+ response = parse(raw_response)
+ success = response.key?("sig")
+ rescue ResponseError => e
+ response = parse(e.response.body)
+ end
+
+ Response.new(
+ success,
+ (success ? "OK" : response["error"]["message"]),
+ response,
+ test: test?,
+ authorization: authorization_from(response)
+ )
+ end
+
+ def authorization_from(response)
+ if response.key?("transaction")
+ response["transaction"]["id"]
+ elsif response.key?("card")
+ response["card"]["token"]
+ end
+ end
+
+ def json_error(raw_response)
+ msg = "Invalid response from app55 server: Received: #{raw_response.inspect})"
+ {
+ "error" => {
+ "message" => msg
+ }
+ }
+ end
+
+ def url(resource)
+ (test? ? self.test_url : self.live_url) + resource
+ end
+
+ def post_data(params)
+ return nil unless params
+
+ params.map do |key, value|
+ next if value.blank?
+ if value.is_a?(Hash)
+ h = {}
+ value.each do |k, v|
+ h["#{key}.#{k}"] = v unless v.blank?
+ end
+ post_data(h)
+ else
+ "#{key}=#{CGI.escape(value.to_s)}"
+ end
+ end.compact.join("&")
+ end
+
+ def headers
+ @@ua ||= JSON.dump(
+ :bindings_version => ActiveMerchant::VERSION,
+ :lang => 'ruby',
+ :lang_version => "#{RUBY_VERSION} p#{RUBY_PATCHLEVEL} (#{RUBY_RELEASE_DATE})",
+ :platform => RUBY_PLATFORM,
+ :publisher => 'active_merchant'
+ )
+
+ {
+ "Authorization" => "Basic " + Base64.strict_encode64(@options[:api_key].to_s + ":" + @options[:api_secret].to_s),
+ "User-Agent" => "ActiveMerchantBindings/#{ActiveMerchant::VERSION}",
+ }
+ end
+ end
+ end
+end
+
diff --git a/lib/active_merchant/billing/gateways/authorize_net.rb b/lib/active_merchant/billing/gateways/authorize_net.rb
index fb2fada9f6f..dc98492d254 100644
--- a/lib/active_merchant/billing/gateways/authorize_net.rb
+++ b/lib/active_merchant/billing/gateways/authorize_net.rb
@@ -39,7 +39,7 @@ class AuthorizeNetGateway < Gateway
APPROVED, DECLINED, ERROR, FRAUD_REVIEW = 1, 2, 3, 4
RESPONSE_CODE, RESPONSE_REASON_CODE, RESPONSE_REASON_TEXT, AUTHORIZATION_CODE = 0, 2, 3, 4
- AVS_RESULT_CODE, TRANSACTION_ID, CARD_CODE_RESPONSE_CODE = 5, 6, 38
+ AVS_RESULT_CODE, TRANSACTION_ID, CARD_CODE_RESPONSE_CODE, CARDHOLDER_AUTH_CODE = 5, 6, 38, 39
self.default_currency = 'USD'
@@ -51,6 +51,7 @@ class AuthorizeNetGateway < Gateway
CARD_CODE_ERRORS = %w( N S )
AVS_ERRORS = %w( A E N R W Z )
AVS_REASON_CODES = %w(27 45)
+ TRANSACTION_ALREADY_ACTIONED = %w(310 311)
AUTHORIZE_NET_ARB_NAMESPACE = 'AnetApi/xml/v1/schema/AnetApiSchema.xsd'
@@ -199,7 +200,7 @@ def credit(money, identification, options = {})
# For example, to charge the customer once every three months the hash would be
# +:interval => { :unit => :months, :length => 3 }+ (REQUIRED)
# * :duration -- A hash containing keys for the :start_date the subscription begins (also the date the
- # initial billing occurs) and the total number of billing :occurences or payments for the subscription. (REQUIRED)
+ # initial billing occurs) and the total number of billing :occurrences or payments for the subscription. (REQUIRED)
def recurring(money, creditcard, options={})
requires!(options, :interval, :duration, :billing_address)
requires!(options[:interval], :length, [:unit, :days, :months])
@@ -294,7 +295,7 @@ def commit(action, money, parameters)
end
def success?(response)
- response[:response_code] == APPROVED
+ response[:response_code] == APPROVED && TRANSACTION_ALREADY_ACTIONED.exclude?(response[:response_reason_code])
end
def fraud_review?(response)
@@ -311,7 +312,8 @@ def parse(body)
:avs_result_code => fields[AVS_RESULT_CODE],
:transaction_id => fields[TRANSACTION_ID],
:card_code => fields[CARD_CODE_RESPONSE_CODE],
- :authorization_code => fields[AUTHORIZATION_CODE]
+ :authorization_code => fields[AUTHORIZATION_CODE],
+ :cardholder_authentication_code => fields[CARDHOLDER_AUTH_CODE]
}
results
end
@@ -383,6 +385,15 @@ def add_customer_data(post, options)
if options.has_key? :ip
post[:customer_ip] = options[:ip]
end
+
+ if options.has_key? :cardholder_authentication_value
+ post[:cardholder_authentication_value] = options[:cardholder_authentication_value]
+ end
+
+ if options.has_key? :authentication_indicator
+ post[:authentication_indicator] = options[:authentication_indicator]
+ end
+
end
# x_duplicate_window won't be sent by default, because sending it changes the response.
diff --git a/lib/active_merchant/billing/gateways/authorize_net_cim.rb b/lib/active_merchant/billing/gateways/authorize_net_cim.rb
index 39aaca66522..bc3c356f5d6 100644
--- a/lib/active_merchant/billing/gateways/authorize_net_cim.rb
+++ b/lib/active_merchant/billing/gateways/authorize_net_cim.rb
@@ -95,7 +95,7 @@ class AuthorizeNetCimGateway < Gateway
# * :test -- +true+ or +false+. If true, perform transactions against the test server.
# Otherwise, perform transactions against the production server.
# * :test_requests -- +true+ or +false+. If true, perform transactions without the
- # test flag. This is useful when you need to generate card declines, AVS or CVV erros.
+ # test flag. This is useful when you need to generate card declines, AVS or CVV errors.
# Will hold the same value as :test by default.
# * :delimiter -- The delimiter used in the direct response. Default is ',' (comma).
def initialize(options = {})
@@ -340,7 +340,7 @@ def update_customer_shipping_address(options)
# ==== Transaction
#
# * :type -- The type of transaction. Can be either :auth_only, :capture_only, :auth_capture, :prior_auth_capture, :refund or :void. (REQUIRED)
- # * :amount -- The amount for the tranaction. Formatted with a decimal. For example "4.95" (CONDITIONAL)
+ # * :amount -- The amount for the transaction. Formatted with a decimal. For example "4.95" (CONDITIONAL)
# - :type == :void (NOT USED)
# - :type == :refund (OPTIONAL)
# - :type == (:auth_only, :capture_only, :auth_capture, :prior_auth_capture) (REQUIRED)
@@ -369,8 +369,8 @@ def update_customer_shipping_address(options)
# - :type = (:prior_auth_capture) (OPTIONAL)
#
# ==== For :type == :refund only
- # * :credit_card_number_masked -- (CONDITIONAL - requied for credit card refunds is :customer_profile_id AND :customer_payment_profile_id are missing)
- # * :bank_routing_number_masked && :bank_account_number_masked -- (CONDITIONAL - requied for electronic check refunds is :customer_profile_id AND :customer_payment_profile_id are missing) (NOT ABLE TO TEST - I keep getting "ACH transactions are not accepted by this merchant." when trying to make a payment and, until that's possible I can't refund (wiseleyb@gmail.com))
+ # * :credit_card_number_masked -- (CONDITIONAL - required for credit card refunds if :customer_profile_id AND :customer_payment_profile_id are missing)
+ # * :bank_routing_number_masked && :bank_account_number_masked -- (CONDITIONAL - required for electronic check refunds if :customer_profile_id AND :customer_payment_profile_id are missing) (NOT ABLE TO TEST - I keep getting "ACH transactions are not accepted by this merchant." when trying to make a payment and, until that's possible I can't refund (wiseleyb@gmail.com))
def create_customer_profile_transaction(options)
requires!(options, :transaction)
requires!(options[:transaction], :type)
@@ -410,13 +410,13 @@ def create_customer_profile_transaction(options)
# * :customer_profile_id -- The Customer Profile ID of the customer to use in this transaction. (CONDITIONAL :customer_payment_profile_id must be included if used)
# * :customer_payment_profile_id -- The Customer Payment Profile ID of the Customer Payment Profile to use in this transaction. (CONDITIONAL :customer_profile_id must be included if used)
#
- # * :credit_card_number_masked -- Four Xs follwed by the last four digits of the credit card (CONDITIONAL - used if customer_profile_id and customer_payment_profile_id aren't given)
+ # * :credit_card_number_masked -- Four Xs followed by the last four digits of the credit card (CONDITIONAL - used if customer_profile_id and customer_payment_profile_id aren't given)
#
- # * :bank_routing_number_masked -- The last four gidits of the routing number to be refunded (CONDITIONAL - must be used with :bank_account_number_masked)
- # * :bank_account_number_masked -- The last four digis of the bank account number to be refunded, Ex. XXXX1234 (CONDITIONAL - must be used with :bank_routing_number_masked)
+ # * :bank_routing_number_masked -- The last four digits of the routing number to be refunded (CONDITIONAL - must be used with :bank_account_number_masked)
+ # * :bank_account_number_masked -- The last four digits of the bank account number to be refunded, Ex. XXXX1234 (CONDITIONAL - must be used with :bank_routing_number_masked)
#
# * :tax - A hash containing tax information for the refund (OPTIONAL - :amount, :name (31 characters), :description (255 characters))
- # * :duty - A hash containting duty information for the refund (OPTIONAL - :amount, :name (31 characters), :description (255 characters))
+ # * :duty - A hash containing duty information for the refund (OPTIONAL - :amount, :name (31 characters), :description (255 characters))
# * :shipping - A hash containing shipping information for the refund (OPTIONAL - :amount, :name (31 characters), :description (255 characters))
def create_customer_profile_transaction_for_refund(options)
requires!(options, :transaction)
diff --git a/lib/active_merchant/billing/gateways/balanced.rb b/lib/active_merchant/billing/gateways/balanced.rb
index 63350ebb677..89496890c49 100644
--- a/lib/active_merchant/billing/gateways/balanced.rb
+++ b/lib/active_merchant/billing/gateways/balanced.rb
@@ -131,6 +131,7 @@ def authorize(money, credit_card, options = {})
post = {}
post[:amount] = money
post[:description] = options[:description]
+ post[:appears_on_statement_as] = options[:appears_on_statement_as] if options[:appears_on_statement_as]
create_or_find_account(post, options)
add_credit_card(post, credit_card, options)
@@ -168,6 +169,7 @@ def purchase(money, credit_card, options = {})
post = {}
post[:amount] = money
post[:description] = options[:description]
+ post[:appears_on_statement_as] = options[:appears_on_statement_as] if options[:appears_on_statement_as]
create_or_find_account(post, options)
add_credit_card(post, credit_card, options)
@@ -197,6 +199,7 @@ def capture(money, authorization, options = {})
post[:hold_uri] = authorization
post[:amount] = money if money
post[:description] = options[:description] if options[:description]
+ post[:appears_on_statement_as] = options[:appears_on_statement_as] if options[:appears_on_statement_as]
post[:on_behalf_of_uri] = options[:on_behalf_of_uri] if options[:on_behalf_of_uri]
create_transaction(:post, @debits_uri, post)
@@ -213,6 +216,7 @@ def capture(money, authorization, options = {})
def void(authorization, options = {})
post = {}
post[:is_void] = true
+ post[:appears_on_statement_as] = options[:appears_on_statement_as] if options[:appears_on_statement_as]
create_transaction(:put, authorization, post)
rescue Error => ex
@@ -246,6 +250,7 @@ def refund(amount, debit_uri = "deprecated", options = {})
post[:debit_uri] = debit_uri
post[:amount] = amount
post[:description] = options[:description]
+ post[:appears_on_statement_as] = options[:appears_on_statement_as] if options[:appears_on_statement_as]
create_transaction(:post, @refunds_uri, post)
rescue Error => ex
failed_response(ex.response)
@@ -261,11 +266,17 @@ def store(credit_card, options = {})
post = {}
account_uri = create_or_find_account(post, options)
if credit_card.respond_to? :number
- add_credit_card(post, credit_card, options)
+ card_uri = add_credit_card(post, credit_card, options)
else
- associate_card_to_account(account_uri, credit_card)
- credit_card
+ card_uri = associate_card_to_account(account_uri, credit_card)
end
+
+ is_test = false
+ if @marketplace_uri
+ is_test = (@marketplace_uri.index("TEST") ? true : false)
+ end
+
+ Response.new(true, "Card stored", {}, :test => is_test, :authorization => [card_uri, account_uri].compact.join(';'))
rescue Error => ex
failed_response(ex.response)
end
diff --git a/lib/active_merchant/billing/gateways/beanstream.rb b/lib/active_merchant/billing/gateways/beanstream.rb
index edc3bb11f02..9b8680ac2ea 100644
--- a/lib/active_merchant/billing/gateways/beanstream.rb
+++ b/lib/active_merchant/billing/gateways/beanstream.rb
@@ -139,7 +139,7 @@ def store(credit_card, options = {})
commit(post, true)
end
- #can't actually delete a secure profile with the supplicaed API. This function sets the status of the profile to closed (C).
+ #can't actually delete a secure profile with the supplicated API. This function sets the status of the profile to closed (C).
#Closed profiles will have to removed manually.
def delete(vault_id)
update(vault_id, false, {:status => "C"})
diff --git a/lib/active_merchant/billing/gateways/bogus.rb b/lib/active_merchant/billing/gateways/bogus.rb
index 3a23de6e8b0..3d1bdd9cf61 100644
--- a/lib/active_merchant/billing/gateways/bogus.rb
+++ b/lib/active_merchant/billing/gateways/bogus.rb
@@ -7,67 +7,67 @@ class BogusGateway < Gateway
SUCCESS_MESSAGE = "Bogus Gateway: Forced success"
FAILURE_MESSAGE = "Bogus Gateway: Forced failure"
ERROR_MESSAGE = "Bogus Gateway: Use CreditCard number ending in 1 for success, 2 for exception and anything else for error"
- CREDIT_ERROR_MESSAGE = "Bogus Gateway: Use CreditCard number ending in 1 for success, 2 for exception and anything else for error"
UNSTORE_ERROR_MESSAGE = "Bogus Gateway: Use trans_id ending in 1 for success, 2 for exception and anything else for error"
CAPTURE_ERROR_MESSAGE = "Bogus Gateway: Use authorization number ending in 1 for exception, 2 for error and anything else for success"
VOID_ERROR_MESSAGE = "Bogus Gateway: Use authorization number ending in 1 for exception, 2 for error and anything else for success"
REFUND_ERROR_MESSAGE = "Bogus Gateway: Use trans_id number ending in 1 for exception, 2 for error and anything else for success"
+ CHECK_ERROR_MESSAGE = "Bogus Gateway: Use bank account number ending in 1 for success, 2 for exception and anything else for error"
self.supported_countries = ['US']
self.supported_cardtypes = [:bogus]
self.homepage_url = 'http://example.com'
self.display_name = 'Bogus'
- def authorize(money, credit_card_or_reference, options = {})
+ def authorize(money, paysource, options = {})
money = amount(money)
- case normalize(credit_card_or_reference)
+ case normalize(paysource)
when /1$/
Response.new(true, SUCCESS_MESSAGE, {:authorized_amount => money}, :test => true, :authorization => AUTHORIZATION )
when /2$/
Response.new(false, FAILURE_MESSAGE, {:authorized_amount => money, :error => FAILURE_MESSAGE }, :test => true)
else
- raise Error, ERROR_MESSAGE
+ raise Error, error_message(paysource)
end
end
- def purchase(money, credit_card_or_reference, options = {})
+ def purchase(money, paysource, options = {})
money = amount(money)
- case normalize(credit_card_or_reference)
+ case normalize(paysource)
when /1$/, AUTHORIZATION
Response.new(true, SUCCESS_MESSAGE, {:paid_amount => money}, :test => true, :authorization => AUTHORIZATION)
when /2$/
Response.new(false, FAILURE_MESSAGE, {:paid_amount => money, :error => FAILURE_MESSAGE },:test => true)
else
- raise Error, ERROR_MESSAGE
+ raise Error, error_message(paysource)
end
end
- def recurring(money, credit_card_or_reference, options = {})
+ def recurring(money, paysource, options = {})
money = amount(money)
- case normalize(credit_card_or_reference)
+ case normalize(paysource)
when /1$/
Response.new(true, SUCCESS_MESSAGE, {:paid_amount => money}, :test => true)
when /2$/
Response.new(false, FAILURE_MESSAGE, {:paid_amount => money, :error => FAILURE_MESSAGE },:test => true)
else
- raise Error, ERROR_MESSAGE
+ raise Error, error_message(paysource)
end
end
- def credit(money, credit_card_or_reference, options = {})
- if credit_card_or_reference.is_a?(String)
+ def credit(money, paysource, options = {})
+ if paysource.is_a?(String)
deprecated CREDIT_DEPRECATION_MESSAGE
- return refund(money, credit_card_or_reference, options)
+ return refund(money, paysource, options)
end
money = amount(money)
- case normalize(credit_card_or_reference)
+ case normalize(paysource)
when /1$/
Response.new(true, SUCCESS_MESSAGE, {:paid_amount => money}, :test => true )
when /2$/
Response.new(false, FAILURE_MESSAGE, {:paid_amount => money, :error => FAILURE_MESSAGE }, :test => true)
else
- raise Error, CREDIT_ERROR_MESSAGE
+ raise Error, error_message(paysource)
end
end
@@ -106,14 +106,14 @@ def void(reference, options = {})
end
end
- def store(credit_card_or_reference, options = {})
- case normalize(credit_card_or_reference)
+ def store(paysource, options = {})
+ case normalize(paysource)
when /1$/
Response.new(true, SUCCESS_MESSAGE, {:billingid => '1'}, :test => true, :authorization => AUTHORIZATION)
when /2$/
Response.new(false, FAILURE_MESSAGE, {:billingid => nil, :error => FAILURE_MESSAGE }, :test => true)
else
- raise Error, ERROR_MESSAGE
+ raise Error, error_message(paysource)
end
end
@@ -130,11 +130,21 @@ def unstore(reference, options = {})
private
- def normalize(credit_card_or_reference)
- if credit_card_or_reference.respond_to?(:number)
- credit_card_or_reference.number
+ def normalize(paysource)
+ if paysource.respond_to?(:account_number) && (paysource.try(:number).blank? || paysource.number.blank?)
+ paysource.account_number
+ elsif paysource.respond_to?(:number)
+ paysource.number
else
- credit_card_or_reference.to_s
+ paysource.to_s
+ end
+ end
+
+ def error_message(paysource)
+ if paysource.respond_to?(:account_number)
+ CHECK_ERROR_MESSAGE
+ elsif paysource.respond_to?(:number)
+ ERROR_MESSAGE
end
end
end
diff --git a/lib/active_merchant/billing/gateways/braintree_blue.rb b/lib/active_merchant/billing/gateways/braintree_blue.rb
index 656b8ec139c..05b68e2529c 100644
--- a/lib/active_merchant/billing/gateways/braintree_blue.rb
+++ b/lib/active_merchant/billing/gateways/braintree_blue.rb
@@ -111,26 +111,20 @@ def void(authorization, options = {})
end
def store(creditcard, options = {})
- commit do
- parameters = {
- :first_name => creditcard.first_name,
- :last_name => creditcard.last_name,
- :email => options[:email],
- :credit_card => {
- :number => creditcard.number,
- :cvv => creditcard.verification_value,
- :expiration_month => creditcard.month.to_s.rjust(2, "0"),
- :expiration_year => creditcard.year.to_s
- }
- }
- result = @braintree_gateway.customer.create(merge_credit_card_options(parameters, options))
- Response.new(result.success?, message_from_result(result),
- {
- :braintree_customer => (customer_hash(result.customer) if result.success?),
- :customer_vault_id => (result.customer.id if result.success?)
- },
- :authorization => (result.customer.id if result.success?)
- )
+ if options[:customer].present?
+ MultiResponse.new.tap do |r|
+ customer_exists_response = nil
+ r.process{customer_exists_response = check_customer_exists(options[:customer])}
+ r.process do
+ if customer_exists_response.params["exists"]
+ add_credit_card_to_customer(creditcard, options)
+ else
+ add_customer_with_credit_card(creditcard, options)
+ end
+ end
+ end
+ else
+ add_customer_with_credit_card(creditcard, options)
end
end
@@ -153,11 +147,11 @@ def update(vault_id, creditcard, options = {})
result = @braintree_gateway.customer.update(vault_id,
:first_name => creditcard.first_name,
:last_name => creditcard.last_name,
- :email => options[:email],
+ :email => scrub_email(options[:email]),
:credit_card => credit_card_params
)
Response.new(result.success?, message_from_result(result),
- :braintree_customer => (customer_hash(@braintree_gateway.customer.find(vault_id)) if result.success?),
+ :braintree_customer => (customer_hash(@braintree_gateway.customer.find(vault_id), :include_credit_cards) if result.success?),
:customer_vault_id => (result.customer.id if result.success?)
)
end
@@ -165,7 +159,11 @@ def update(vault_id, creditcard, options = {})
def unstore(customer_vault_id, options = {})
commit do
- @braintree_gateway.customer.delete(customer_vault_id)
+ if(!customer_vault_id && options[:credit_card_token])
+ @braintree_gateway.credit_card.delete(options[:credit_card_token])
+ else
+ @braintree_gateway.customer.delete(customer_vault_id)
+ end
Response.new(true, "OK")
end
end
@@ -173,6 +171,87 @@ def unstore(customer_vault_id, options = {})
private
+ def check_customer_exists(customer_vault_id)
+ commit do
+ begin
+ @braintree_gateway.customer.find(customer_vault_id)
+ ActiveMerchant::Billing::Response.new(true, "Customer found", {exists: true}, authorization: customer_vault_id)
+ rescue Braintree::NotFoundError
+ ActiveMerchant::Billing::Response.new(true, "Customer not found", {exists: false})
+ end
+ end
+ end
+
+ def add_customer_with_credit_card(creditcard, options)
+ commit do
+ parameters = {
+ :first_name => creditcard.first_name,
+ :last_name => creditcard.last_name,
+ :email => scrub_email(options[:email]),
+ :id => options[:customer],
+ :credit_card => {
+ :number => creditcard.number,
+ :cvv => creditcard.verification_value,
+ :expiration_month => creditcard.month.to_s.rjust(2, "0"),
+ :expiration_year => creditcard.year.to_s,
+ :token => options[:credit_card_token]
+ }
+ }
+ result = @braintree_gateway.customer.create(merge_credit_card_options(parameters, options))
+ Response.new(result.success?, message_from_result(result),
+ {
+ :braintree_customer => (customer_hash(result.customer, :include_credit_cards) if result.success?),
+ :customer_vault_id => (result.customer.id if result.success?),
+ :credit_card_token => (result.customer.credit_cards[0].token if result.success?)
+ },
+ :authorization => (result.customer.id if result.success?)
+ )
+ end
+ end
+
+ def add_credit_card_to_customer(credit_card, options)
+ commit do
+ parameters = {
+ customer_id: options[:customer],
+ token: options[:credit_card_token],
+ number: credit_card.number,
+ cvv: credit_card.verification_value,
+ expiration_month: credit_card.month.to_s.rjust(2, "0"),
+ expiration_year: credit_card.year.to_s,
+ }
+ parameters[:billing_address] = map_address(options[:billing_address]) if options[:billing_address]
+
+ result = @braintree_gateway.credit_card.create(parameters)
+ ActiveMerchant::Billing::Response.new(
+ result.success?,
+ message_from_result(result),
+ {
+ customer_vault_id: (result.credit_card.customer_id if result.success?),
+ credit_card_token: (result.credit_card.token if result.success?)
+ },
+ authorization: (result.credit_card.customer_id if result.success?)
+ )
+ end
+ end
+
+ def scrub_email(email)
+ return nil unless email.present?
+ return nil if (
+ email !~ /^.+@[^\.]+(\.[^\.]+)+[a-z]$/i ||
+ email =~ /\.(con|met)$/i
+ )
+ email
+ end
+
+ def scrub_zip(zip)
+ return nil unless zip.present?
+ return nil if(
+ zip.gsub(/[^a-z0-9]/i, '').length > 9 ||
+ zip =~ /[^a-z0-9\- ]/i
+ )
+ zip
+ end
+
def merge_credit_card_options(parameters, options)
valid_options = {}
options.each do |key, value|
@@ -193,7 +272,7 @@ def map_address(address)
:company => address[:company],
:locality => address[:city],
:region => address[:state],
- :postal_code => address[:zip],
+ :postal_code => scrub_zip(address[:zip]),
}
if(address[:country] || address[:country_code_alpha2])
mapped[:country_code_alpha2] = (address[:country] || address[:country_code_alpha2])
@@ -281,25 +360,29 @@ def extract_refund_args(args)
end
end
- def customer_hash(customer)
- credit_cards = customer.credit_cards.map do |cc|
- {
- "bin" => cc.bin,
- "expiration_date" => cc.expiration_date,
- "token" => cc.token,
- "last_4" => cc.last_4,
- "card_type" => cc.card_type,
- "masked_number" => cc.masked_number
- }
- end
-
- {
+ def customer_hash(customer, include_credit_cards=false)
+ hash = {
"email" => customer.email,
"first_name" => customer.first_name,
"last_name" => customer.last_name,
- "credit_cards" => credit_cards,
"id" => customer.id
}
+
+ if include_credit_cards
+ hash["credit_cards"] = customer.credit_cards.map do |cc|
+ {
+ "bin" => cc.bin,
+ "expiration_date" => cc.expiration_date,
+ "token" => cc.token,
+ "last_4" => cc.last_4,
+ "card_type" => cc.card_type,
+ "masked_number" => cc.masked_number,
+ "token" => cc.token
+ }
+ end
+ end
+
+ hash
end
def transaction_hash(transaction)
@@ -365,7 +448,7 @@ def create_transaction_parameters(money, credit_card_or_vault_id, options)
:order_id => options[:order_id],
:customer => {
:id => options[:store] == true ? "" : options[:store],
- :email => options[:email]
+ :email => scrub_email(options[:email])
},
:options => {
:store_in_vault => options[:store] ? true : false,
@@ -373,6 +456,8 @@ def create_transaction_parameters(money, credit_card_or_vault_id, options)
}
}
+ parameters[:custom_fields] = options[:custom_fields]
+ parameters[:device_data] = options[:device_data] if options[:device_data]
if merchant_account_id = (options[:merchant_account_id] || @merchant_account_id)
parameters[:merchant_account_id] = merchant_account_id
end
diff --git a/lib/active_merchant/billing/gateways/card_stream_modern.rb b/lib/active_merchant/billing/gateways/card_stream_modern.rb
index 1d3393fa22d..984de4b28b9 100644
--- a/lib/active_merchant/billing/gateways/card_stream_modern.rb
+++ b/lib/active_merchant/billing/gateways/card_stream_modern.rb
@@ -114,7 +114,8 @@ def parse(body)
pairs = body.split("&")
pairs.each do |pair|
a = pair.split("=")
- result[a[0].to_sym] = CGI.unescape(a[1])
+ #Make sure there is a value, else set it to empty string
+ result[a[0].to_sym] = a[1] ? CGI.unescape(a[1]) : ""
end
result
end
diff --git a/lib/active_merchant/billing/gateways/conekta.rb b/lib/active_merchant/billing/gateways/conekta.rb
new file mode 100644
index 00000000000..2389106acff
--- /dev/null
+++ b/lib/active_merchant/billing/gateways/conekta.rb
@@ -0,0 +1,233 @@
+module ActiveMerchant #:nodoc:
+ module Billing #:nodoc:
+ class ConektaGateway < Gateway
+ self.live_url = 'https://api.conekta.io/'
+
+ self.supported_countries = ['MX']
+ self.supported_cardtypes = [:visa, :master]
+ self.homepage_url = 'https://conekta.io/'
+ self.display_name = 'Conekta Gateway'
+ self.money_format = :cents
+ self.default_currency = 'MXN'
+
+ def initialize(options = {})
+ requires!(options, :key)
+ options[:version] ||= '0.2.0'
+ super
+ end
+
+ def purchase(money, payment_source, options = {})
+ post = {}
+
+ add_order(post, money, options)
+ add_payment_source(post, payment_source, options)
+ add_details_data(post, options)
+
+ commit(:post, 'charges', post)
+ end
+
+ def authorize(money, payment_source, options = {})
+ post = {}
+
+ add_order(post, money, options)
+ add_payment_source(post, payment_source, options)
+ add_details_data(post, options)
+
+ post[:capture] = false
+ commit(:post, "charges", post)
+ end
+
+ def capture(identifier, money, options = {})
+ post = {}
+
+ post[:order_id] = identifier
+ add_order(post, money, options)
+
+ commit(:post, "charges/#{identifier}/capture", post)
+ end
+
+ def refund(identifier, money, options)
+ post = {}
+
+ post[:order_id] = identifier
+ add_order(post, money, options)
+
+ commit(:post, "charges/#{identifier}/refund", post)
+ end
+
+ def store(creditcard, options = {})
+ post = {}
+ add_payment_source(post, creditcard, options)
+ post[:name] = options[:name]
+ post[:email] = options[:email]
+
+ path = if options[:customer]
+ "customers/#{CGI.escape(options[:customer])}"
+ else
+ 'customers'
+ end
+
+ commit(:post, path, post)
+ end
+
+ def unstore(customer_id, options = {})
+ commit(:delete, "customers/#{CGI.escape(customer_id)}", nil)
+ end
+
+ private
+
+ def add_order(post, money, options)
+ post[:description] = options[:description]
+ post[:reference_id] = options[:order_id]
+ post[:amount] = amount(money)
+ end
+
+ def add_details_data(post, options)
+ details = {}
+ details[:name] = options[:customer]
+ details[:email] = options[:email]
+ details[:phone] = options[:phone]
+ details[:device_fingerprint] = options[:device_fingerprint]
+ details[:ip] = options[:ip]
+ add_billing_address(details, options)
+ add_line_items(details, options)
+ add_shipment(details, options)
+
+ post[:details] = details
+ end
+
+ def add_shipment(post, options)
+ shipment = {}
+ shipment[:carrier] = options[:carrier]
+ shipment[:service] = options[:service]
+ shipment[:tracking_number] = options[:tracking_number]
+ shipment[:price] = options[:price]
+ add_shipment_address(shipment, options)
+ post[:shipment] = shipment
+ end
+
+ def add_shipment_address(post, options)
+ address = {}
+ address[:street1] = options[:address1]
+ address[:street2] = options[:address2]
+ address[:street3] = options[:address3]
+ address[:city] = options[:city]
+ address[:state] = options[:state]
+ address[:country] = options[:country]
+ address[:zip] = options[:zip]
+ post[:address] = address
+ end
+
+ def add_line_items(post, options)
+ post[:line_items] = (options[:line_items] || []).collect do |line_item|
+ line_item
+ end
+ end
+
+ def add_billing_address(post, options)
+ address = {}
+ address[:street1] = options[:address1]
+ address[:street2] = options[:address2]
+ address[:street3] = options[:address3]
+ address[:city] = options[:city]
+ address[:state] = options[:state]
+ address[:country] = options[:country]
+ address[:zip] = options[:zip]
+ address[:company_name] = options[:company_name]
+ address[:tax_id] = options[:tax_id]
+ address[:name] = options[:name]
+ address[:phone] = options[:phone]
+ address[:email] = options[:email]
+ post[:billing_address] = address
+ end
+
+ def add_address(post, options)
+ address = {}
+ address[:street1] = options[:address1]
+ address[:street2] = options[:address2]
+ address[:street3] = options[:address3]
+ address[:city] = options[:city]
+ address[:state] = options[:state]
+ address[:country] = options[:country]
+ address[:zip] = options[:zip]
+ post[:address] = address
+ end
+
+ def add_payment_source(post, payment_source, options)
+ if payment_source.kind_of?(String)
+ post[:card] = payment_source
+ elsif payment_source.respond_to?(:number)
+ card = {}
+ card[:name] = payment_source.name
+ card[:cvc] = payment_source.verification_value
+ card[:number] = payment_source.number
+ card[:exp_month] = "#{sprintf("%02d", payment_source.month)}"
+ card[:exp_year] = "#{"#{payment_source.year}"[-2, 2]}"
+ post[:card] = card
+ add_address(post[:card], options)
+ end
+ end
+
+ def parse(body)
+ return {} unless body
+ JSON.parse(body)
+ end
+
+ def headers(meta)
+ @@ua ||= JSON.dump({
+ :bindings_version => ActiveMerchant::VERSION,
+ :lang => 'ruby',
+ :lang_version => "#{RUBY_VERSION} p#{RUBY_PATCHLEVEL} (#{RUBY_RELEASE_DATE})",
+ :platform => RUBY_PLATFORM,
+ :publisher => 'active_merchant'
+ })
+
+ {
+ "Accept" => "application/vnd.conekta-v#{options[:version]}+json",
+ "Authorization" => "Basic " + Base64.encode64("#{options[:key]}:"),
+ "RaiseHtmlError" => "false",
+ "User-Agent" => "Conekta ActiveMerchantBindings/#{ActiveMerchant::VERSION}",
+ "X-Conekta-Client-User-Agent" => @@ua,
+ "X-Conekta-Client-User-Metadata" => meta.to_json
+ }
+ end
+
+ def commit(method, url, parameters, options = {})
+ success = false
+ begin
+ raw_response = parse(ssl_request(method, live_url + url, (parameters ? parameters.to_query : nil), headers(options[:meta])))
+ success = (raw_response.key?("object") && (raw_response["object"] != "error"))
+ rescue ResponseError => e
+ raw_response = response_error(e.response.body)
+ rescue JSON::ParserError
+ raw_response = json_error(raw_response)
+ end
+
+ Response.new(
+ success,
+ raw_response["message"],
+ raw_response,
+ :test => test?,
+ :authorization => raw_response["id"]
+ )
+ end
+
+ def response_error(raw_response)
+ begin
+ parse(raw_response)
+ rescue JSON::ParserError
+ json_error(raw_response)
+ end
+ end
+
+ def json_error(raw_response)
+ msg = 'Invalid response received from the Conekta API.'
+ msg += " (The raw response returned by the API was #{raw_response.inspect})"
+ {
+ "message" => msg
+ }
+ end
+ end
+ end
+end
+
diff --git a/lib/active_merchant/billing/gateways/cyber_source.rb b/lib/active_merchant/billing/gateways/cyber_source.rb
index f72480808d6..c959b66e309 100644
--- a/lib/active_merchant/billing/gateways/cyber_source.rb
+++ b/lib/active_merchant/billing/gateways/cyber_source.rb
@@ -24,7 +24,7 @@ module Billing #:nodoc:
# CyberSource what kind of item you are selling. It is used when
# calculating tax/VAT.
# * All transactions use dollar values.
- # * To process pinless debit cards throught the pinless debit card
+ # * To process pinless debit cards through the pinless debit card
# network, your Cybersource merchant account must accept pinless
# debit card payments.
class CyberSourceGateway < Gateway
@@ -102,7 +102,7 @@ class CyberSourceGateway < Gateway
# :vat_reg_number => your VAT registration number
#
# :nexus => "WI CA QC" sets the states/provinces where you have a physical
- # presense for tax purposes
+ # presence for tax purposes
#
# :ignore_avs => true don't want to use AVS so continue processing even
# if AVS would have failed
diff --git a/lib/active_merchant/billing/gateways/elavon.rb b/lib/active_merchant/billing/gateways/elavon.rb
index ddc4559b937..d079eabca9c 100644
--- a/lib/active_merchant/billing/gateways/elavon.rb
+++ b/lib/active_merchant/billing/gateways/elavon.rb
@@ -36,7 +36,7 @@ class ElavonGateway < Gateway
self.live_url = 'https://www.myvirtualmerchant.com/VirtualMerchant/process.do'
self.display_name = 'Elavon MyVirtualMerchant'
- self.supported_countries = ['US', 'CA']
+ self.supported_countries = %w(US CA PR DE IE NO PL LU BE NL)
self.supported_cardtypes = [:visa, :master, :american_express, :discover]
self.homepage_url = 'http://www.elavon.com/'
diff --git a/lib/active_merchant/billing/gateways/eway_rapid.rb b/lib/active_merchant/billing/gateways/eway_rapid.rb
index 12616b3f320..380e4be0a4f 100644
--- a/lib/active_merchant/billing/gateways/eway_rapid.rb
+++ b/lib/active_merchant/billing/gateways/eway_rapid.rb
@@ -1,5 +1,4 @@
-require "nokogiri"
-require "cgi"
+require 'json'
module ActiveMerchant #:nodoc:
module Billing #:nodoc:
@@ -11,7 +10,7 @@ class EwayRapidGateway < Gateway
self.supported_countries = ["AU"]
self.supported_cardtypes = [:visa, :master, :american_express, :diners_club]
self.homepage_url = "http://www.eway.com.au/"
- self.display_name = "eWAY Rapid 3.0"
+ self.display_name = "eWAY Rapid 3.1"
self.default_currency = "AUD"
def initialize(options = {})
@@ -19,203 +18,219 @@ def initialize(options = {})
super
end
- # Public: Run a purchase transaction. Treats the Rapid 3.0 transparent
- # redirect as an API endpoint in order to conform to the standard
- # ActiveMerchant #purchase API.
+ # Public: Run a purchase transaction.
#
- # amount - The monetary amount of the transaction in cents.
- # options - A standard ActiveMerchant options hash:
- # :order_id - A merchant-supplied identifier for the
- # transaction (optional).
- # :description - A merchant-supplied description of the
- # transaction (optional).
- # :currency - Three letter currency code for the
- # transaction (default: "AUD")
- # :billing_address - Standard ActiveMerchant address hash
- # (optional).
- # :shipping_address - Standard ActiveMerchant address hash
- # (optional).
- # :ip - The ip of the consumer initiating the
- # transaction (optional).
- # :application_id - A string identifying the application
- # submitting the transaction
- # (default: "https://github.com/Shopify/active_merchant")
+ # amount - The monetary amount of the transaction in cents.
+ # payment_method - The payment method or authorization token returned from store.
+ # options - A standard ActiveMerchant options hash:
+ # :transaction_type - One of: Purchase (default), MOTO
+ # or Recurring. For stored card payments (aka - TokenPayments),
+ # this must be either MOTO or Recurring.
+ # :order_id - A merchant-supplied identifier for the
+ # transaction (optional).
+ # :description - A merchant-supplied description of the
+ # transaction (optional).
+ # :currency - Three letter currency code for the
+ # transaction (default: "AUD")
+ # :billing_address - Standard ActiveMerchant address hash
+ # (optional).
+ # :shipping_address - Standard ActiveMerchant address hash
+ # (optional).
+ # :ip - The ip of the consumer initiating the
+ # transaction (optional).
+ # :application_id - A string identifying the application
+ # submitting the transaction
+ # (default: "https://github.com/Shopify/active_merchant")
#
- # Returns an ActiveMerchant::Billing::Response object
+ # Returns an ActiveMerchant::Billing::Response object where authorization is the Transaction ID on success
def purchase(amount, payment_method, options={})
- MultiResponse.new.tap do |r|
- # Rather than follow the redirect, we detect the 302 and capture the
- # token out of the Location header in the run_purchase step. But we
- # still need a placeholder url to pass to eWay, and that is what
- # example.com is used for here.
- r.process{setup_purchase(amount, options.merge(:redirect_url => "http://example.com/"))}
- r.process{run_purchase(r.authorization, payment_method, r.params["formactionurl"])}
- r.process{status(r.authorization)}
- end
+ params = {}
+ add_metadata(params, options)
+ add_invoice(params, amount, options)
+ add_customer_data(params, options)
+ add_credit_card(params, payment_method, options)
+ commit(url_for('Transaction'), params)
end
- # Public: Acquire the token necessary to run a transparent redirect.
+ # Public: Refund a transaction.
#
- # amount - The monetary amount of the transaction in cents.
- # options - A supplemented ActiveMerchant options hash:
- # :redirect_url - The url to return the customer to after
- # the transparent redirect is completed
- # (required).
- # :order_id - A merchant-supplied identifier for the
- # transaction (optional).
- # :description - A merchant-supplied description of the
- # transaction (optional).
- # :currency - Three letter currency code for the
- # transaction (default: "AUD")
- # :billing_address - Standard ActiveMerchant address hash
- # (optional).
- # :shipping_address - Standard ActiveMerchant address hash
- # (optional).
- # :ip - The ip of the consumer initiating the
- # transaction (optional).
- # :application_id - A string identifying the application
- # submitting the transaction
- # (default: "https://github.com/Shopify/active_merchant")
+ # money - The monetary amount of the transaction in cents
+ # identification - The transaction id which is returned in the
+ # authorization of the successful purchase transaction
+ # options - A standard ActiveMerchant options hash:
+ # :order_id - A merchant-supplied identifier for the
+ # transaction (optional).
+ # :description - A merchant-supplied description of the
+ # transaction (optional).
+ # :currency - Three letter currency code for the
+ # transaction (default: "AUD")
+ # :billing_address - Standard ActiveMerchant address hash
+ # (optional).
+ # :shipping_address - Standard ActiveMerchant address hash
+ # (optional).
+ # :ip - The ip of the consumer initiating the
+ # transaction (optional).
+ # :application_id - A string identifying the application
+ # submitting the transaction
+ # (default: "https://github.com/Shopify/active_merchant")
#
- # Returns an EwayRapidResponse object, which conforms to the
- # ActiveMerchant::Billing::Response API, but also exposes #form_url.
- def setup_purchase(amount, options={})
- requires!(options, :redirect_url)
- request = build_xml_request("CreateAccessCodeRequest") do |doc|
- add_metadata(doc, options)
- add_invoice(doc, amount, options)
- add_customer_data(doc, options)
- end
-
- commit(url_for("CreateAccessCode"), request)
+ # Returns an ActiveMerchant::Billing::Response object
+ def refund(money, identification, options = {})
+ params = {}
+ add_metadata(params, options)
+ add_invoice(params, money, options.merge(refund_transaction_id: identification))
+ add_customer_data(params, options)
+ commit(url_for("Transaction/#{identification}/Refund"), params)
end
- # Public: Retrieve the status of a transaction.
+ # Public: Store card details and return a valid token
#
- # identification - The Eway Rapid 3.0 access code for the transaction
- # (returned as the response.authorization by
- # #setup_purchase).
+ # payment_method - The payment method or nil if :customer_token is provided
+ # options - A supplemented ActiveMerchant options hash:
+ # :order_id - A merchant-supplied identifier for the
+ # transaction (optional).
+ # :description - A merchant-supplied description of the
+ # transaction (optional).
+ # :billing_address - Standard ActiveMerchant address hash
+ # (required).
+ # :ip - The ip of the consumer initiating the
+ # transaction (optional).
+ # :application_id - A string identifying the application
+ # submitting the transaction
+ # (default: "https://github.com/Shopify/active_merchant")
#
- # Returns an EwayRapidResponse object.
- def status(identification)
- request = build_xml_request("GetAccessCodeResultRequest") do |doc|
- doc.AccessCode identification
- end
- commit(url_for("GetAccessCodeResult"), request)
+ # Returns an ActiveMerchant::Billing::Response object where the authorization is the customer_token on success
+ def store(payment_method, options = {})
+ requires!(options, :billing_address)
+ params = {}
+ add_metadata(params, options)
+ add_invoice(params, 0, options)
+ add_customer_data(params, options)
+ add_credit_card(params, payment_method, options)
+ params['Method'] = 'CreateTokenCustomer'
+ commit(url_for("Transaction"), params)
end
- # Public: Store card details and return a valid token
+ # Public: Update a customer's data
#
- # options - A supplemented ActiveMerchant options hash:
- # :order_id - A merchant-supplied identifier for the
- # transaction (optional).
- # :billing_address - Standard ActiveMerchant address hash
- # (required).
- # :ip - The ip of the consumer initiating the
- # transaction (optional).
- # :application_id - A string identifying the application
- # submitting the transaction
- # (default: "https://github.com/Shopify/active_merchant")
- def store(payment_method, options = {})
- requires!(options, :billing_address)
- purchase(0, payment_method, options.merge(:request_method => "CreateTokenCustomer"))
+ # customer_token - The customer token returned in the authorization of
+ # a successful store transaction.
+ # payment_method - The payment method or nil if :customer_token is provided
+ # options - A supplemented ActiveMerchant options hash:
+ # :order_id - A merchant-supplied identifier for the
+ # transaction (optional).
+ # :description - A merchant-supplied description of the
+ # transaction (optional).
+ # :billing_address - Standard ActiveMerchant address hash
+ # (optional).
+ # :ip - The ip of the consumer initiating the
+ # transaction (optional).
+ # :application_id - A string identifying the application
+ # submitting the transaction
+ # (default: "https://github.com/Shopify/active_merchant")
+ #
+ # Returns an ActiveMerchant::Billing::Response object where the authorization is the customer_token on success
+ def update(customer_token, payment_method, options = {})
+ params = {}
+ add_metadata(params, options)
+ add_invoice(params, 0, options)
+ add_customer_data(params, options)
+ add_credit_card(params, payment_method, options)
+ add_customer_token(params, customer_token)
+ params['Method'] = 'UpdateTokenCustomer'
+ commit(url_for("Transaction"), params)
end
private
- def run_purchase(identification, payment_method, endpoint)
- post = {
- "accesscode" => identification
- }
- add_credit_card(post, payment_method)
-
- commit_form(endpoint, build_form_request(post), :identification => identification)
- end
-
- def add_metadata(doc, options)
- doc.RedirectUrl(options[:redirect_url])
- doc.CustomerIP options[:ip] if options[:ip]
- doc.Method options[:request_method] || "ProcessPayment"
- doc.DeviceID(options[:application_id] || application_id)
+ def add_metadata(params, options)
+ params['RedirectUrl'] = options[:redirect_url] || 'http://example.com'
+ params['CustomerIP'] = options[:ip] if options[:ip]
+ params['TransactionType'] = options[:transaction_type] || 'Purchase'
+ params['DeviceID'] = options[:application_id] || application_id
end
- def add_invoice(doc, money, options)
- doc.Payment do
- doc.TotalAmount amount(money)
- doc.InvoiceReference options[:order_id]
- doc.InvoiceDescription options[:description]
- currency_code = (options[:currency] || currency(money) || default_currency)
- doc.CurrencyCode currency_code
+ def add_invoice(params, money, options)
+ currency_code = options[:currency] || currency(money)
+ invoice = {
+ 'TotalAmount' => localized_amount(money, currency_code),
+ 'InvoiceReference' => options[:order_id],
+ 'InvoiceDescription' => options[:description],
+ 'CurrencyCode' => currency_code,
+ }
+ if options[:refund_transaction_id]
+ # must include the original transaction id for refunds
+ invoice['TransactionID'] = options[:refund_transaction_id] if options[:refund_transaction_id]
+ params['Refund'] = invoice
+ else
+ params['Payment'] = invoice
end
end
- def add_customer_data(doc, options)
- doc.Customer do
- add_address(doc, (options[:billing_address] || options[:address]), {:email => options[:email]})
- end
- doc.ShippingAddress do
- add_address(doc, options[:shipping_address], {:skip_company => true})
- end
+ def add_customer_data(params, options)
+ params['Customer'] ||= {}
+ add_address(params['Customer'], (options[:billing_address] || options[:address]), {:email => options[:email]})
+ params['ShippingAddress'] = {}
+ add_address(params['ShippingAddress'], options[:shipping_address], {:skip_company => true})
end
- def add_address(doc, address, options={})
+ def add_address(params, address, options={})
return unless address
- if name = address[:name]
- parts = name.split(/\s+/)
- doc.FirstName parts.shift if parts.size > 1
- doc.LastName parts.join(" ")
- end
- doc.Title address[:title]
- doc.CompanyName address[:company] unless options[:skip_company]
- doc.Street1 address[:address1]
- doc.Street2 address[:address2]
- doc.City address[:city]
- doc.State address[:state]
- doc.PostalCode address[:zip]
- doc.Country address[:country].to_s.downcase
- doc.Phone address[:phone]
- doc.Fax address[:fax]
- doc.Email options[:email]
- end
- def add_credit_card(post, credit_card)
- post["cardname"] = credit_card.name
- post["cardnumber"] = credit_card.number
- post["cardexpirymonth"] = credit_card.month
- post["cardexpiryyear"] = credit_card.year
- post["cardcvn"] = credit_card.verification_value
+ if address[:name]
+ parts = address[:name].split(/\s+/)
+ params['FirstName'] = parts.shift if parts.size > 1
+ params['LastName'] = parts.join(" ")
+ end
+ params['Title'] = address[:title]
+ params['CompanyName'] = address[:company] unless options[:skip_company]
+ params['Street1'] = address[:address1]
+ params['Street2'] = address[:address2]
+ params['City'] = address[:city]
+ params['State'] = address[:state]
+ params['PostalCode'] = address[:zip]
+ params['Country'] = address[:country].to_s.downcase
+ params['Phone'] = address[:phone]
+ params['Fax'] = address[:fax]
+ params['Email'] = options[:email]
end
- def build_xml_request(root)
- builder = Nokogiri::XML::Builder.new
- builder.__send__(root) do |doc|
- yield(doc)
+ def add_credit_card(params, credit_card, options)
+ return unless credit_card
+ params['Customer'] ||= {}
+ if credit_card.respond_to? :number
+ params['Method'] = 'ProcessPayment'
+ card_details = params['Customer']['CardDetails'] = {}
+ card_details['Name'] = credit_card.name
+ card_details['Number'] = credit_card.number
+ card_details['ExpiryMonth'] = "%02d" % (credit_card.month || 0)
+ card_details['ExpiryYear'] = "%02d" % (credit_card.year || 0)
+ card_details['CVN'] = credit_card.verification_value
+ else
+ params['Method'] = 'TokenPayment'
+ add_customer_token(params, credit_card)
end
- builder.to_xml
end
- def build_form_request(post)
- request = []
- post.each do |key, value|
- request << "EWAY_#{key.upcase}=#{CGI.escape(value.to_s)}"
- end
- request.join("&")
+ def add_customer_token(params, token)
+ params['Customer'] ||= {}
+ params['Customer']['TokenCustomerID'] = token
end
def url_for(action)
- (test? ? test_url : live_url) + action + ".xml"
+ (test? ? test_url : live_url) + action
end
- def commit(url, request, form_post=false)
+ def commit(url, params)
headers = {
"Authorization" => ("Basic " + Base64.strict_encode64(@options[:login].to_s + ":" + @options[:password].to_s).chomp),
- "Content-Type" => "text/xml"
+ "Content-Type" => "application/json"
}
-
+ request = params.to_json
raw = parse(ssl_post(url, request, headers))
succeeded = success?(raw)
- EwayRapidResponse.new(
+ ActiveMerchant::Billing::Response.new(
succeeded,
message_from(succeeded, raw),
raw,
@@ -225,56 +240,32 @@ def commit(url, request, form_post=false)
:cvv_result => cvv_result_from(raw)
)
rescue ActiveMerchant::ResponseError => e
- return EwayRapidResponse.new(false, e.response.message, {:status_code => e.response.code}, :test => test?)
+ return ActiveMerchant::Billing::Response.new(false, e.response.message, {:status_code => e.response.code}, :test => test?)
end
- def commit_form(url, request, parameters)
- http_response = raw_ssl_request(:post, url, request)
-
- success = (http_response.code.to_s == "302")
- message = (success ? "Succeeded" : http_response.body)
- authorization = parameters[:identification] if success
-
- Response.new(success, message, {:location => http_response["Location"]}, :authorization => authorization, :test => test?)
- end
-
- def parse(xml)
- response = {}
-
- doc = Nokogiri::XML(xml)
- doc.root.xpath("*").each do |node|
- if (node.elements.size == 0)
- response[node.name.downcase.to_sym] = node.text
- else
- node.elements.each do |childnode|
- name = "#{node.name.downcase}_#{childnode.name.downcase}"
- response[name.to_sym] = childnode.text
- end
- end
- end unless doc.root.nil?
-
- response
+ def parse(data)
+ JSON.parse(data)
end
def success?(response)
- if response[:errors]
+ if response['Errors']
false
- elsif response[:responsecode] == "00"
+ elsif response['ResponseCode'] == "00"
true
- elsif response[:transactionstatus]
- (response[:transactionstatus] == "true")
+ elsif response['TransactionStatus']
+ (response['TransactionStatus'] == true)
else
true
end
end
def message_from(succeeded, response)
- if response[:errors]
- (MESSAGES[response[:errors]] || response[:errors])
- elsif response[:responsecode]
- ActiveMerchant::Billing::EwayGateway::MESSAGES[response[:responsecode]]
- elsif response[:responsemessage]
- (MESSAGES[response[:responsemessage]] || response[:responsemessage])
+ if response['Errors']
+ (MESSAGES[response['Errors']] || response['Errors'])
+ elsif response['Responsecode']
+ ActiveMerchant::Billing::EwayGateway::MESSAGES[response['ResponseCode']]
+ elsif response['ResponseMessage']
+ (MESSAGES[response['ResponseMessage']] || response['ResponseMessage'])
elsif succeeded
"Succeeded"
else
@@ -283,11 +274,14 @@ def message_from(succeeded, response)
end
def authorization_from(response)
- response[:accesscode]
+ # Note: TransactionID is always null for store requests, but TokenCustomerID is also sent back for purchase from
+ # stored card transactions so we give precendence to TransactionID
+ response['TransactionID'] || response['Customer']['TokenCustomerID']
end
def avs_result_from(response)
- code = case response[:verification_address]
+ verification = response['Verification'] || {}
+ code = case verification['Address']
when "Valid"
"M"
when "Invalid"
@@ -299,7 +293,8 @@ def avs_result_from(response)
end
def cvv_result_from(response)
- case response[:verification_cvn]
+ verification = response['Verification'] || {}
+ case verification['CVN']
when "Valid"
"M"
when "Invalid"
@@ -309,16 +304,25 @@ def cvv_result_from(response)
end
end
- class EwayRapidResponse < ActiveMerchant::Billing::Response
- def form_url
- params["formactionurl"]
- end
- end
-
MESSAGES = {
+ 'A2000' => 'Transaction Approved Successful',
+ 'A2008' => 'Honour With Identification Successful',
+ 'A2010' => 'Approved For Partial Amount Successful',
+ 'A2011' => 'Approved, VIP Successful',
+ 'A2016' => 'Approved, Update Track 3 Successful',
+ 'S5000' => 'System Error',
+ 'S5085' => 'Started 3dSecure',
+ 'S5086' => 'Routed 3dSecure',
+ 'S5087' => 'Completed 3dSecure',
+ 'S5088' => 'PayPal Transaction Created',
+ 'S5099' => 'Incomplete (Access Code in progress/incomplete)',
+ 'S5010' => 'Unknown error returned by gateway',
'V6000' => 'Validation error',
'V6001' => 'Invalid CustomerIP',
'V6002' => 'Invalid DeviceID',
+ 'V6003' => 'Invalid Request PartnerID',
+ 'V6004' => 'Invalid Request Method',
+ 'V6010' => 'Invalid TransactionType, account not certified for eCome only MOTO or Recurring available',
'V6011' => 'Invalid Payment TotalAmount',
'V6012' => 'Invalid Payment InvoiceDescription',
'V6013' => 'Invalid Payment InvoiceNumber',
@@ -385,7 +389,8 @@ def form_url
'V6107' => 'Invalid EWAY_ACCESSCODE',
'V6108' => 'Invalid CustomerHostAddress',
'V6109' => 'Invalid UserAgent',
- 'V6110' => 'Invalid EWAY_CARDNUMBER'
+ 'V6110' => 'Invalid EWAY_CARDNUMBER',
+ 'V6111' => 'Unauthorised API Access, Account Not PCI Certified'
}
end
end
diff --git a/lib/active_merchant/billing/gateways/litle.rb b/lib/active_merchant/billing/gateways/litle.rb
index 83ce2bc28dc..afb742a09f2 100755
--- a/lib/active_merchant/billing/gateways/litle.rb
+++ b/lib/active_merchant/billing/gateways/litle.rb
@@ -171,11 +171,11 @@ def build_response(kind, litle_response, valid_responses=%w(000))
Response.new(
valid_responses.include?(detail['response']),
detail['message'],
- { :litleOnlineResponse => response },
- :authorization => authorization_from(detail, kind),
- :avs_result => { :code => fraud['avs'] },
- :cvv_result => fraud['cvv'],
- :test => test?
+ { litleOnlineResponse: response, response_code: detail['response'] },
+ authorization: authorization_from(detail, kind),
+ avs_result: { :code => fraud['avs'] },
+ cvv_result: fraud['cvv'],
+ test: test?
)
else
Response.new(false, response['message'], :litleOnlineResponse => response, :test => test?)
diff --git a/lib/active_merchant/billing/gateways/merchant_warrior.rb b/lib/active_merchant/billing/gateways/merchant_warrior.rb
index 9ee22a3c3b1..8b22c837b68 100644
--- a/lib/active_merchant/billing/gateways/merchant_warrior.rb
+++ b/lib/active_merchant/billing/gateways/merchant_warrior.rb
@@ -75,7 +75,7 @@ def add_transaction(post, identification)
end
def add_address(post, options)
- return unless(address = options[:address])
+ return unless(address = (options[:billing_address] || options[:address]))
post['customerName'] = address[:name]
post['customerCountry'] = address[:country]
@@ -86,7 +86,7 @@ def add_address(post, options)
end
def add_product(post, options)
- post['transactionProduct'] = options[:transaction_product]
+ post['transactionProduct'] = options[:description]
end
def add_payment_method(post, payment_method)
diff --git a/lib/active_merchant/billing/gateways/mercury.rb b/lib/active_merchant/billing/gateways/mercury.rb
index 4f969015904..12faffb2c02 100644
--- a/lib/active_merchant/billing/gateways/mercury.rb
+++ b/lib/active_merchant/billing/gateways/mercury.rb
@@ -77,6 +77,11 @@ def void(authorization, options={})
commit('VoidSale', request)
end
+ def store(credit_card, options={})
+ request = build_card_lookup_request(credit_card, options)
+ commit('CardLookup', request)
+ end
+
private
def build_non_authorized_request(action, money, credit_card, options)
@@ -129,6 +134,23 @@ def build_authorized_request(action, money, authorization, credit_card, options)
xml = xml.target!
end
+ def build_card_lookup_request(credit_card, options)
+ xml = Builder::XmlMarkup.new
+
+ xml.tag! "TStream" do
+ xml.tag! "Transaction" do
+ xml.tag! 'TranType', 'CardLookup'
+ xml.tag! 'RecordNo', 'RecordNumberRequested'
+ xml.tag! 'Frequency', 'OneTime'
+
+ xml.tag! 'Memo', options[:description]
+ add_customer_data(xml, options)
+ add_credit_card(xml, credit_card, options)
+ end
+ end
+ xml.target!
+ end
+
def add_invoice(xml, invoice_no, ref_no, options)
if /^\d+$/ !~ invoice_no.to_s
raise ArgumentError.new("order_id '#{invoice_no}' is not numeric as required by Mercury")
diff --git a/lib/active_merchant/billing/gateways/moneris.rb b/lib/active_merchant/billing/gateways/moneris.rb
index 5ff1121c316..68588262f80 100644
--- a/lib/active_merchant/billing/gateways/moneris.rb
+++ b/lib/active_merchant/billing/gateways/moneris.rb
@@ -167,7 +167,7 @@ def crediting_params(authorization, options = {})
}.merge(options)
end
- # Splits an +authorization+ param and retrives the order id and
+ # Splits an +authorization+ param and retrieves the order id and
# transaction number in that order.
def split_authorization(authorization)
if authorization.nil? || authorization.empty? || authorization !~ /;/
diff --git a/lib/active_merchant/billing/gateways/moneris_us.rb b/lib/active_merchant/billing/gateways/moneris_us.rb
index 92feec27397..2113e166ce4 100644
--- a/lib/active_merchant/billing/gateways/moneris_us.rb
+++ b/lib/active_merchant/billing/gateways/moneris_us.rb
@@ -111,7 +111,7 @@ def crediting_params(authorization, options = {})
}.merge(options)
end
- # Splits an +authorization+ param and retrives the order id and
+ # Splits an +authorization+ param and retrieves the order id and
# transaction number in that order.
def split_authorization(authorization)
if authorization.nil? || authorization.empty? || authorization !~ /;/
diff --git a/lib/active_merchant/billing/gateways/nab_transact.rb b/lib/active_merchant/billing/gateways/nab_transact.rb
index 456d582b343..8e75cbf5943 100644
--- a/lib/active_merchant/billing/gateways/nab_transact.rb
+++ b/lib/active_merchant/billing/gateways/nab_transact.rb
@@ -127,11 +127,13 @@ def build_reference_request(money, reference, options)
xml.tag! 'purchaseOrderNo', order_id
xml.tag! 'preauthID', preauth_id
+ add_metadata(xml, options)
+
xml.target!
end
#Generate payment request XML
- # - API is set to allow multiple Txn's but currentlu only allows one
+ # - API is set to allow multiple Txn's but currently only allows one
# - txnSource = 23 - (XML)
def build_request(action, body)
xml = Builder::XmlMarkup.new
diff --git a/lib/active_merchant/billing/gateways/netpay.rb b/lib/active_merchant/billing/gateways/netpay.rb
index babf9542502..b950d33073b 100644
--- a/lib/active_merchant/billing/gateways/netpay.rb
+++ b/lib/active_merchant/billing/gateways/netpay.rb
@@ -18,7 +18,7 @@ module Billing #:nodoc:
# transaction. After this, a refund should be performed instead.
#
# In addition to the regular ActiveMerchant transaction options, NETPAY
- # also supports a `:mode` parameter. This allows testing to be peformed
+ # also supports a `:mode` parameter. This allows testing to be performed
# in production and force specific results.
#
# * 'P' - Production
diff --git a/lib/active_merchant/billing/gateways/orbital.rb b/lib/active_merchant/billing/gateways/orbital.rb
index c26ebbac4a9..85eacc75a5e 100644
--- a/lib/active_merchant/billing/gateways/orbital.rb
+++ b/lib/active_merchant/billing/gateways/orbital.rb
@@ -80,6 +80,25 @@ class OrbitalGateway < Gateway
"EUR" => '978'
}
+ CURRENCY_EXPONENTS = {
+ "AUD" => '2',
+ "CAD" => '2',
+ "CZK" => '2',
+ "DKK" => '2',
+ "HKD" => '2',
+ "ICK" => '2',
+ "JPY" => '0',
+ "MXN" => '2',
+ "NZD" => '2',
+ "NOK" => '2',
+ "SGD" => '2',
+ "SEK" => '2',
+ "CHF" => '2',
+ "GBP" => '2',
+ "USD" => '2',
+ "EUR" => '2'
+ }
+
# INDUSTRY TYPES
ECOMMERCE_TRANSACTION = 'EC'
RECURRING_PAYMENT_TRANSACTION = 'RC'
@@ -146,7 +165,7 @@ def initialize(options = {})
# A – Authorization request
def authorize(money, creditcard, options = {})
order = build_new_order_xml(AUTH_ONLY, money, options) do |xml|
- add_creditcard(xml, creditcard, options[:currency]) unless creditcard.nil? && options[:profile_txn]
+ add_creditcard(xml, creditcard, options[:currency])
add_address(xml, creditcard, options)
if @options[:customer_profiles]
add_customer_data(xml, options)
@@ -159,7 +178,7 @@ def authorize(money, creditcard, options = {})
# AC – Authorization and Capture
def purchase(money, creditcard, options = {})
order = build_new_order_xml(AUTH_AND_CAPTURE, money, options) do |xml|
- add_creditcard(xml, creditcard, options[:currency]) unless creditcard.nil? && options[:profile_txn]
+ add_creditcard(xml, creditcard, options[:currency])
add_address(xml, creditcard, options)
if @options[:customer_profiles]
add_customer_data(xml, options)
@@ -327,11 +346,13 @@ def add_customer_address(xml, options)
end
def add_creditcard(xml, creditcard, currency=nil)
- xml.tag! :AccountNum, creditcard.number
- xml.tag! :Exp, expiry_date(creditcard)
+ unless creditcard.nil?
+ xml.tag! :AccountNum, creditcard.number
+ xml.tag! :Exp, expiry_date(creditcard)
+ end
xml.tag! :CurrencyCode, currency_code(currency)
- xml.tag! :CurrencyExponent, '2' # Will need updating to support currencies such as the Yen.
+ xml.tag! :CurrencyExponent, currency_exponents(currency)
# If you are trying to collect a Card Verification Number
# (CardSecVal) for a Visa or Discover transaction, pass one of these values:
@@ -342,17 +363,19 @@ def add_creditcard(xml, creditcard, currency=nil)
# Null-fill this attribute OR
# Do not submit the attribute at all.
# - http://download.chasepaymentech.com/docs/orbital/orbital_gateway_xml_specification.pdf
- if %w( visa discover ).include?(creditcard.brand)
- xml.tag! :CardSecValInd, (creditcard.verification_value? ? '1' : '9')
+ unless creditcard.nil?
+ if %w( visa discover ).include?(creditcard.brand)
+ xml.tag! :CardSecValInd, (creditcard.verification_value? ? '1' : '9')
+ end
+ xml.tag! :CardSecVal, creditcard.verification_value if creditcard.verification_value?
end
- xml.tag! :CardSecVal, creditcard.verification_value if creditcard.verification_value?
end
def add_refund(xml, currency=nil)
xml.tag! :AccountNum, nil
xml.tag! :CurrencyCode, currency_code(currency)
- xml.tag! :CurrencyExponent, '2' # Will need updating to support currencies such as the Yen.
+ xml.tag! :CurrencyExponent, currency_exponents(currency)
end
def add_managed_billing(xml, options)
@@ -540,6 +563,10 @@ def currency_code(currency)
CURRENCY_CODES[(currency || self.default_currency)].to_s
end
+ def currency_exponents(currency)
+ CURRENCY_EXPONENTS[(currency || self.default_currency)].to_s
+ end
+
def expiry_date(credit_card)
"#{format(credit_card.month, :two_digits)}#{format(credit_card.year, :two_digits)}"
end
diff --git a/lib/active_merchant/billing/gateways/pac_net_raven.rb b/lib/active_merchant/billing/gateways/pac_net_raven.rb
new file mode 100644
index 00000000000..e6b9a8a1416
--- /dev/null
+++ b/lib/active_merchant/billing/gateways/pac_net_raven.rb
@@ -0,0 +1,187 @@
+module ActiveMerchant #:nodoc:
+ module Billing #:nodoc:
+ class PacNetRavenGateway < Gateway
+ self.test_url = 'https://demo.deepcovelabs.com/realtime/'
+ self.live_url = 'https://raven.pacnetservices.com/realtime/'
+
+ self.supported_countries = ['US']
+ self.supported_cardtypes = [:visa, :master, :american_express, :discover]
+ self.money_format = :cents
+ self.default_currency = 'USD'
+ self.homepage_url = 'http://www.pacnetservices.com/'
+ self.display_name = 'Raven PacNet'
+
+ def initialize(options = {})
+ requires!(options, :user, :secret, :prn)
+ super
+ end
+
+ def authorize(money, creditcard, options = {})
+ post = {}
+ add_creditcard(post, creditcard)
+ add_currency_code(post, money, options)
+ add_address(post, options)
+ post['PRN'] = @options[:prn]
+
+ commit('cc_preauth', money, post)
+ end
+
+ def purchase(money, creditcard, options = {})
+ post = {}
+ add_currency_code(post, money, options)
+ add_creditcard(post, creditcard)
+ add_address(post, options)
+ post['PRN'] = @options[:prn]
+
+ commit('cc_debit', money, post)
+ end
+
+ def void(authorization, options = {})
+ post = {}
+ post['TrackingNumber'] = authorization
+ post['PymtType'] = options[:pymt_type] || 'cc_debit'
+
+ commit('void', nil, post)
+ end
+
+ def capture(money, authorization, options = {})
+ post = {}
+ post['PreauthNumber'] = authorization
+ post['PRN'] = @options[:prn]
+ add_currency_code(post, money, options)
+
+ commit('cc_settle', money, post)
+ end
+
+ def refund(money, template_number, options = {})
+ post = {}
+ post['PRN'] = @options[:prn]
+ post['TemplateNumber'] = template_number
+ add_currency_code(post, money, options)
+
+ commit('cc_refund', money, post)
+ end
+
+ private
+
+ def add_creditcard(post, creditcard)
+ post['CardNumber'] = creditcard.number
+ post['Expiry'] = expdate(creditcard)
+ post['CVV2'] = creditcard.verification_value if creditcard.verification_value
+ end
+
+ def add_currency_code(post, money, options)
+ post['Currency'] = options[:currency] || currency(money)
+ end
+
+ def add_address(post, options)
+ if address = options[:billing_address] || options[:address]
+ post['BillingStreetAddressLineOne'] = address[:address1].to_s
+ post['BillingStreetAddressLineFour'] = address[:address2].to_s
+ post['BillingPostalCode'] = address[:zip].to_s
+ end
+ end
+
+ def parse(body)
+ Hash[body.split('&').map{|x| x.split('=').map{|x| CGI.unescape(x)}}]
+ end
+
+ def commit(action, money, parameters)
+ parameters['Amount'] = amount(money) unless action == 'void'
+
+ data = ssl_post url(action), post_data(action, parameters)
+
+ response = parse(data)
+ response[:action] = action
+
+ message = message_from(response)
+
+ test_mode = test? || message =~ /TESTMODE/
+
+ Response.new(success?(response), message, response,
+ :test => test_mode,
+ :authorization => response['TrackingNumber'],
+ :fraud_review => fraud_review?(response),
+ :avs_result => { :postal_match => response['AVSPostalResponseCode'], :street_match => response['AVSAddressResponseCode'] },
+ :cvv_result => response['CVV2ResponseCode']
+ )
+ end
+
+ def url(action)
+ (test? ? self.test_url : self.live_url) + endpoint(action)
+ end
+
+ def endpoint(action)
+ return 'void' if action == 'void'
+ 'submit'
+ end
+
+ def fraud_review?(response)
+ false
+ end
+
+ def success?(response)
+ if %w(cc_settle cc_debit cc_preauth cc_refund).include?(response[:action])
+ !response['ApprovalCode'].nil? and response['ErrorCode'].nil? and response['Status'] == 'Approved'
+ elsif response[:action] = 'void'
+ !response['ApprovalCode'].nil? and response['ErrorCode'].nil? and response['Status'] == 'Voided'
+ end
+ end
+
+ def message_from(response)
+ return response['Message'] if response['Message']
+
+ if response['Status'] == 'Approved'
+ "This transaction has been approved"
+ elsif response['Status'] == 'Declined'
+ "This transaction has been declined"
+ elsif response['Status'] == 'Voided'
+ "This transaction has been voided"
+ else
+ response['Status']
+ end
+ end
+
+ def post_data(action, parameters = {})
+ post = {}
+
+ post['PymtType'] = action
+ post['RAPIVersion'] = '2'
+ post['UserName'] = @options[:user]
+ post['Timestamp'] = timestamp
+ post['RequestID'] = request_id
+ post['Signature'] = signature(action, post, parameters)
+
+ request = post.merge(parameters).collect { |key, value| "#{key}=#{CGI.escape(value.to_s)}" }.join("&")
+ request
+ end
+
+ def timestamp
+ Time.now.strftime("%Y-%m-%dT%H:%M:%S.Z")
+ end
+
+ def request_id
+ (0...21).map{(65+rand(26)).chr}.join.downcase
+ end
+
+ def signature(action, post, parameters = {})
+ string = if %w(cc_settle cc_debit cc_preauth cc_refund).include?(action)
+ post['UserName'] + post['Timestamp'] + post['RequestID'] + post['PymtType'] + parameters['Amount'].to_s + parameters['Currency']
+ elsif action == 'void'
+ post['UserName'] + post['Timestamp'] + post['RequestID'] + parameters['TrackingNumber']
+ else
+ post['UserName']
+ end
+ Digest::HMAC.hexdigest(string, @options[:secret], Digest::SHA1)
+ end
+
+ def expdate(creditcard)
+ year = sprintf("%.4i", creditcard.year)
+ month = sprintf("%.2i", creditcard.month)
+
+ "#{month}#{year[-2..-1]}"
+ end
+ end
+ end
+end
+
diff --git a/lib/active_merchant/billing/gateways/pay_junction.rb b/lib/active_merchant/billing/gateways/pay_junction.rb
index ceb2e184d93..ada083f48ca 100644
--- a/lib/active_merchant/billing/gateways/pay_junction.rb
+++ b/lib/active_merchant/billing/gateways/pay_junction.rb
@@ -73,16 +73,16 @@ module Billing #:nodoc:
#
# PayJunction Field ActiveMerchant Use
#
- # dc_logon provide as :login value to gateway instantation
+ # dc_logon provide as :login value to gateway instantiation
# dc_password provide as :password value to gateway instantiation
#
# dc_name will be retrieved from credit_card.name
- # dc_first_name :first_name on CreditCard object instantation
- # dc_last_name :last_name on CreditCard object instantation
- # dc_number :number on CreditCard object instantation
- # dc_expiration_month :month on CreditCard object instantation
- # dc_expiration_year :year on CreditCard object instantation
- # dc_verification_number :verification_value on CC object instantation
+ # dc_first_name :first_name on CreditCard object instantiation
+ # dc_last_name :last_name on CreditCard object instantiation
+ # dc_number :number on CreditCard object instantiation
+ # dc_expiration_month :month on CreditCard object instantiation
+ # dc_expiration_year :year on CreditCard object instantiation
+ # dc_verification_number :verification_value on CC object instantiation
#
# dc_transaction_amount include as argument to method for your transaction type
# dc_transaction_type do nothing, set by your transaction type
diff --git a/lib/active_merchant/billing/gateways/payex.rb b/lib/active_merchant/billing/gateways/payex.rb
new file mode 100644
index 00000000000..0aaf0f33bec
--- /dev/null
+++ b/lib/active_merchant/billing/gateways/payex.rb
@@ -0,0 +1,402 @@
+require "nokogiri"
+module ActiveMerchant #:nodoc:
+ module Billing #:nodoc:
+ class PayexGateway < Gateway
+ self.live_url = 'https://external.payex.com/'
+ self.test_url = 'https://test-external.payex.com/'
+
+ self.money_format = :cents
+ self.supported_countries = ['SE', 'NO', 'DK']
+ self.supported_cardtypes = [:visa, :master, :american_express, :discover]
+ self.homepage_url = 'http://payex.com/'
+ self.display_name = 'Payex'
+ self.default_currency = "EUR"
+
+ # NOTE: the PurchaseCC uses a different url for test transactions
+ TEST_CONFINED_URL = 'https://test-confined.payex.com/'
+
+ TRANSACTION_STATUS = {
+ sale: '0',
+ initialize: '1',
+ credit: '2',
+ authorize: '3',
+ cancel: '4',
+ failure: '5',
+ capture: '6',
+ }
+
+ SOAP_ACTIONS = {
+ initialize: { name: 'Initialize8', url: 'pxorder/pxorder.asmx', xmlns: 'http://external.payex.com/PxOrder/' },
+ purchasecc: { name: 'PurchaseCC', url: 'pxconfined/pxorder.asmx', xmlns: 'http://confined.payex.com/PxOrder/', confined: true},
+ cancel: { name: 'Cancel2', url: 'pxorder/pxorder.asmx', xmlns: 'http://external.payex.com/PxOrder/' },
+ capture: { name: 'Capture5', url: 'pxorder/pxorder.asmx', xmlns: 'http://external.payex.com/PxOrder/' },
+ credit: { name: 'Credit5', url: 'pxorder/pxorder.asmx', xmlns: 'http://external.payex.com/PxOrder/' },
+ create_agreement: { name: 'CreateAgreement3', url: 'pxagreement/pxagreement.asmx', xmlns: 'http://external.payex.com/PxAgreement/' },
+ delete_agreement: { name: 'DeleteAgreement', url: 'pxagreement/pxagreement.asmx', xmlns: 'http://external.payex.com/PxAgreement/' },
+ autopay: { name: 'AutoPay3', url: 'pxagreement/pxagreement.asmx', xmlns: 'http://external.payex.com/PxAgreement/' },
+ }
+
+ def initialize(options = {})
+ requires!(options, :account, :encryption_key)
+ super
+ end
+
+ # Public: Send an authorize Payex request
+ #
+ # amount - The monetary amount of the transaction in cents.
+ # payment_method - The Active Merchant payment method or the +store+ authorization for stored transactions.
+ # options - A standard ActiveMerchant options hash:
+ # :currency - Three letter currency code for the transaction (default: "EUR")
+ # :order_id - The unique order ID for this transaction (required).
+ # :product_number - The merchant product number (default: '1').
+ # :description - The merchant description for this product (default: The :order_id).
+ # :ip - The client IP address (default: '127.0.0.1').
+ # :vat - The vat amount (optional).
+ #
+ # Returns an ActiveMerchant::Billing::Response object
+ def authorize(amount, payment_method, options = {})
+ requires!(options, :order_id)
+ amount = amount(amount)
+ if payment_method.respond_to?(:number)
+ # credit card authorization
+ MultiResponse.new.tap do |r|
+ r.process {send_initialize(amount, true, options)}
+ r.process {send_purchasecc(payment_method, r.params['orderref'])}
+ end
+ else
+ # stored authorization
+ send_autopay(amount, payment_method, true, options)
+ end
+
+ end
+
+ # Public: Send a purchase Payex request
+ #
+ # amount - The monetary amount of the transaction in cents.
+ # payment_method - The Active Merchant payment method or the +store+ authorization for stored transactions.
+ # options - A standard ActiveMerchant options hash:
+ # :currency - Three letter currency code for the transaction (default: "EUR")
+ # :order_id - The unique order ID for this transaction (required).
+ # :product_number - The merchant product number (default: '1').
+ # :description - The merchant description for this product (default: The :order_id).
+ # :ip - The client IP address (default: '127.0.0.1').
+ # :vat - The vat amount (optional).
+ #
+ # Returns an ActiveMerchant::Billing::Response object
+ def purchase(amount, payment_method, options = {})
+ requires!(options, :order_id)
+ amount = amount(amount)
+ if payment_method.respond_to?(:number)
+ # credit card purchase
+ MultiResponse.new.tap do |r|
+ r.process {send_initialize(amount, false, options)}
+ r.process {send_purchasecc(payment_method, r.params['orderref'])}
+ end
+ else
+ # stored purchase
+ send_autopay(amount, payment_method, false, options)
+ end
+ end
+
+ # Public: Capture money from a previously authorized transaction
+ #
+ # money - The amount to capture
+ # authorization - The authorization token from the authorization request
+ #
+ # Returns an ActiveMerchant::Billing::Response object
+ def capture(money, authorization, options = {})
+ amount = amount(money)
+ send_capture(amount, authorization)
+ end
+
+ # Public: Voids an authorize transaction
+ #
+ # authorization - The authorization returned from the successful authorize transaction.
+ # options - A standard ActiveMerchant options hash
+ #
+ # Returns an ActiveMerchant::Billing::Response object
+ def void(authorization, options={})
+ send_cancel(authorization)
+ end
+
+ # Public: Refunds a purchase transaction
+ #
+ # money - The amount to refund
+ # authorization - The authorization token from the purchase request.
+ # options - A standard ActiveMerchant options hash:
+ # :order_id - The unique order ID for this transaction (required).
+ # :vat_amount - The vat amount (optional).
+ #
+ # Returns an ActiveMerchant::Billing::Response object
+ def refund(money, authorization, options = {})
+ requires!(options, :order_id)
+ amount = amount(money)
+ send_credit(authorization, amount, options)
+ end
+
+ # Public: Stores a credit card and creates a Payex agreement with a customer
+ #
+ # creditcard - The credit card to store.
+ # options - A standard ActiveMerchant options hash:
+ # :order_id - The unique order ID for this transaction (required).
+ # :merchant_ref - A reference that links this agreement to something the merchant takes money for (default: '1')
+ # :currency - Three letter currency code for the transaction (default: "EUR")
+ # :product_number - The merchant product number (default: '1').
+ # :description - The merchant description for this product (default: The :order_id).
+ # :ip - The client IP address (default: '127.0.0.1').
+ # :max_amount - The maximum amount to allow to be charged (default: 100000).
+ # :vat - The vat amount (optional).
+ #
+ # Returns an ActiveMerchant::Billing::Response object where the authorization is set to the agreement_ref which is used for stored payments.
+ def store(creditcard, options = {})
+ requires!(options, :order_id)
+ amount = amount(1) # 1 cent for authorization
+ MultiResponse.run(:first) do |r|
+ r.process {send_create_agreement(options)}
+ r.process {send_initialize(amount, true, options.merge({agreement_ref: r.authorization}))}
+ order_ref = r.params['orderref']
+ r.process {send_purchasecc(creditcard, order_ref)}
+ end
+ end
+
+ # Public: Unstores a customer's credit card and deletes their Payex agreement.
+ #
+ # authorization - The authorization token from the store request.
+ #
+ # Returns an ActiveMerchant::Billing::Response object
+ def unstore(authorization, options = {})
+ send_delete_agreement(authorization)
+ end
+
+ private
+
+ def send_initialize(amount, is_auth, options = {})
+ properties = {
+ accountNumber: @options[:account],
+ purchaseOperation: is_auth ? 'AUTHORIZATION' : 'SALE',
+ price: amount,
+ priceArgList: nil,
+ currency: (options[:currency] || default_currency),
+ vat: options[:vat] || 0,
+ orderID: options[:order_id],
+ productNumber: options[:product_number] || '1',
+ description: options[:description] || options[:order_id],
+ clientIPAddress: options[:client_ip_address] || '127.0.0.1',
+ clientIdentifier: nil,
+ additionalValues: nil,
+ externalID: nil,
+ returnUrl: 'http://example.net', # set to dummy value since this is not used but is required
+ view: 'CREDITCARD',
+ agreementRef: options[:agreement_ref], # this is used to attach a stored agreement to a transaction as part of the store card
+ cancelUrl: nil,
+ clientLanguage: nil
+ }
+ hash_fields = [:accountNumber, :purchaseOperation, :price, :priceArgList, :currency, :vat, :orderID,
+ :productNumber, :description, :clientIPAddress, :clientIdentifier, :additionalValues,
+ :externalID, :returnUrl, :view, :agreementRef, :cancelUrl, :clientLanguage]
+ add_request_hash(properties, hash_fields)
+ soap_action = SOAP_ACTIONS[:initialize]
+ request = build_xml_request(soap_action, properties)
+ commit(soap_action, request)
+ end
+
+ def send_purchasecc(payment_method, order_ref)
+ properties = {
+ accountNumber: @options[:account],
+ orderRef: order_ref,
+ transactionType: 1, # online payment
+ cardNumber: payment_method.number,
+ cardNumberExpireMonth: "%02d" % payment_method.month,
+ cardNumberExpireYear: "%02d" % payment_method.year,
+ cardHolderName: payment_method.name,
+ cardNumberCVC: payment_method.verification_value
+ }
+ hash_fields = [:accountNumber, :orderRef, :transactionType, :cardNumber, :cardNumberExpireMonth,
+ :cardNumberExpireYear, :cardNumberCVC, :cardHolderName]
+ add_request_hash(properties, hash_fields)
+
+ soap_action = SOAP_ACTIONS[:purchasecc]
+ request = build_xml_request(soap_action, properties)
+ commit(soap_action, request)
+ end
+
+ def send_autopay(amount, authorization, is_auth, options = {})
+ properties = {
+ accountNumber: @options[:account],
+ agreementRef: authorization,
+ price: amount,
+ productNumber: options[:product_number] || '1',
+ description: options[:description] || options[:order_id],
+ orderId: options[:order_id],
+ purchaseOperation: is_auth ? 'AUTHORIZATION' : 'SALE',
+ currency: (options[:currency] || default_currency),
+ }
+ hash_fields = [:accountNumber, :agreementRef, :price, :productNumber, :description, :orderId, :purchaseOperation, :currency]
+ add_request_hash(properties, hash_fields)
+
+ soap_action = SOAP_ACTIONS[:autopay]
+ request = build_xml_request(soap_action, properties)
+ commit(soap_action, request)
+ end
+
+ def send_capture(amount, transaction_number, options = {})
+ properties = {
+ accountNumber: @options[:account],
+ transactionNumber: transaction_number,
+ amount: amount,
+ orderId: options[:order_id] || '',
+ vatAmount: options[:vat_amount] || 0,
+ additionalValues: ''
+ }
+ hash_fields = [:accountNumber, :transactionNumber, :amount, :orderId, :vatAmount, :additionalValues]
+ add_request_hash(properties, hash_fields)
+
+ soap_action = SOAP_ACTIONS[:capture]
+ request = build_xml_request(soap_action, properties)
+ commit(soap_action, request)
+ end
+
+ def send_credit(transaction_number, amount, options = {})
+ properties = {
+ accountNumber: @options[:account],
+ transactionNumber: transaction_number,
+ amount: amount,
+ orderId: options[:order_id],
+ vatAmount: options[:vat_amount] || 0,
+ additionalValues: ''
+ }
+ hash_fields = [:accountNumber, :transactionNumber, :amount, :orderId, :vatAmount, :additionalValues]
+ add_request_hash(properties, hash_fields)
+
+ soap_action = SOAP_ACTIONS[:credit]
+ request = build_xml_request(soap_action, properties)
+ commit(soap_action, request)
+ end
+
+ def send_cancel(transaction_number)
+ properties = {
+ accountNumber: @options[:account],
+ transactionNumber: transaction_number,
+ }
+ hash_fields = [:accountNumber, :transactionNumber]
+ add_request_hash(properties, hash_fields)
+
+ soap_action = SOAP_ACTIONS[:cancel]
+ request = build_xml_request(soap_action, properties)
+ commit(soap_action, request)
+ end
+
+ def send_create_agreement(options)
+ properties = {
+ accountNumber: @options[:account],
+ merchantRef: options[:merchant_ref] || '1',
+ description: options[:description] || options[:order_id],
+ purchaseOperation: 'SALE',
+ maxAmount: options[:max_amount] || 100000, # default to 1,000
+ notifyUrl: '',
+ startDate: options[:startDate] || '',
+ stopDate: options[:stopDate] || ''
+ }
+ hash_fields = [:accountNumber, :merchantRef, :description, :purchaseOperation, :maxAmount, :notifyUrl, :startDate, :stopDate]
+ add_request_hash(properties, hash_fields)
+
+ soap_action = SOAP_ACTIONS[:create_agreement]
+ request = build_xml_request(soap_action, properties)
+ commit(soap_action, request)
+ end
+
+ def send_delete_agreement(authorization)
+ properties = {
+ accountNumber: @options[:account],
+ agreementRef: authorization,
+ }
+ hash_fields = [:accountNumber, :agreementRef]
+ add_request_hash(properties, hash_fields)
+
+ soap_action = SOAP_ACTIONS[:delete_agreement]
+ request = build_xml_request(soap_action, properties)
+ commit(soap_action, request)
+ end
+
+ def url_for(soap_action)
+ base_url = test? ? (soap_action[:confined] ? TEST_CONFINED_URL : test_url) : live_url
+ File.join(base_url, soap_action[:url])
+ end
+
+ # this will add a hash to the passed in properties as required by Payex requests
+ def add_request_hash(properties, fields)
+ data = fields.map { |e| properties[e] }
+ data << @options[:encryption_key]
+ properties['hash_'] = Digest::MD5.hexdigest(data.join(''))
+ end
+
+ def build_xml_request(soap_action, properties)
+ builder = Nokogiri::XML::Builder.new
+ builder.__send__('soap12:Envelope', {'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
+ 'xmlns:xsd' => 'http://www.w3.org/2001/XMLSchema',
+ 'xmlns:soap12' => 'http://www.w3.org/2003/05/soap-envelope'}) do |root|
+ root.__send__('soap12:Body') do |body|
+ body.__send__(soap_action[:name], xmlns: soap_action[:xmlns]) do |doc|
+ properties.each do |key, val|
+ doc.send(key, val)
+ end
+ end
+ end
+ end
+ builder.to_xml
+ end
+
+ def parse(xml)
+ response = {}
+
+ xmldoc = Nokogiri::XML(xml)
+ body = xmldoc.xpath("//soap:Body/*[1]")[0].inner_text
+
+ doc = Nokogiri::XML(body)
+
+ doc.root.xpath("*").each do |node|
+ if (node.elements.size == 0)
+ response[node.name.downcase.to_sym] = node.text
+ else
+ node.elements.each do |childnode|
+ name = "#{node.name.downcase}_#{childnode.name.downcase}"
+ response[name.to_sym] = childnode.text
+ end
+ end
+ end unless doc.root.nil?
+
+ response
+ end
+
+ # Commits all requests to the Payex soap endpoint
+ def commit(soap_action, request)
+ url = url_for(soap_action)
+ headers = {
+ 'Content-Type' => 'application/soap+xml; charset=utf-8',
+ 'Content-Length' => request.size.to_s
+ }
+ response = parse(ssl_post(url, request, headers))
+ Response.new(success?(response),
+ message_from(response),
+ response,
+ test: test?,
+ authorization: build_authorization(response)
+ )
+ end
+
+ def build_authorization(response)
+ # agreementref is for the store transaction, everything else gets transactionnumber
+ response[:transactionnumber] || response[:agreementref]
+ end
+
+ def success?(response)
+ response[:status_errorcode] == 'OK' && response[:transactionstatus] != TRANSACTION_STATUS[:failure]
+ end
+
+ def message_from(response)
+ response[:status_description]
+ end
+ end
+ end
+end
+
diff --git a/lib/active_merchant/billing/gateways/payflow.rb b/lib/active_merchant/billing/gateways/payflow.rb
index 770c426d8fe..4f8c63271c9 100644
--- a/lib/active_merchant/billing/gateways/payflow.rb
+++ b/lib/active_merchant/billing/gateways/payflow.rb
@@ -19,21 +19,26 @@ def authorize(money, credit_card_or_reference, options = {})
commit(request, options)
end
- def purchase(money, credit_card_or_reference, options = {})
- request = build_sale_or_authorization_request(:purchase, money, credit_card_or_reference, options)
+ def purchase(money, funding_source, options = {})
+ request = build_sale_or_authorization_request(:purchase, money, funding_source, options)
commit(request, options)
end
- def credit(money, identification_or_credit_card, options = {})
- if identification_or_credit_card.is_a?(String)
+ def credit(money, funding_source, options = {})
+ case
+ when funding_source.is_a?(String)
deprecated CREDIT_DEPRECATION_MESSAGE
# Perform referenced credit
- refund(money, identification_or_credit_card, options)
- else
+ refund(money, funding_source, options)
+ when funding_source.is_a?(CreditCard)
# Perform non-referenced credit
- request = build_credit_card_request(:credit, money, identification_or_credit_card, options)
+ request = build_credit_card_request(:credit, money, funding_source, options)
+ commit(request, options)
+ when funding_source.is_a?(Check)
+ request = build_check_request(:credit, money, funding_source, options)
commit(request, options)
+ else raise ArgumentError, "Unsupported funding source provided"
end
end
@@ -76,11 +81,15 @@ def express
end
private
- def build_sale_or_authorization_request(action, money, credit_card_or_reference, options)
- if credit_card_or_reference.is_a?(String)
- build_reference_sale_or_authorization_request(action, money, credit_card_or_reference, options)
- else
- build_credit_card_request(action, money, credit_card_or_reference, options)
+ def build_sale_or_authorization_request(action, money, funding_source, options)
+ case
+ when funding_source.is_a?(String)
+ build_reference_sale_or_authorization_request(action, money, funding_source, options)
+ when funding_source.is_a?(CreditCard)
+ build_credit_card_request(action, money, funding_source, options)
+ when funding_source.is_a?(Check)
+ build_check_request(action, money, funding_source, options)
+ else raise ArgumentError, "Unsupported funding source provided"
end
end
@@ -147,6 +156,31 @@ def build_credit_card_request(action, money, credit_card, options)
xml.target!
end
+ def build_check_request(action, money, check, options)
+ xml = Builder::XmlMarkup.new
+ xml.tag! TRANSACTIONS[action] do
+ xml.tag! 'PayData' do
+ xml.tag! 'Invoice' do
+ xml.tag! 'CustIP', options[:ip] unless options[:ip].blank?
+ xml.tag! 'InvNum', options[:order_id].to_s.gsub(/[^\w.]/, '') unless options[:order_id].blank?
+ xml.tag! 'Description', options[:description] unless options[:description].blank?
+ xml.tag! 'BillTo' do
+ xml.tag! 'Name', check.name
+ end
+ xml.tag! 'TotalAmt', amount(money), 'Currency' => options[:currency] || currency(money)
+ end
+ xml.tag! 'Tender' do
+ xml.tag! 'ACH' do
+ xml.tag! 'AcctType', check.account_type == 'checking' ? 'C' : 'S'
+ xml.tag! 'AcctNum', check.account_number
+ xml.tag! 'ABA', check.routing_number
+ end
+ end
+ end
+ end
+ xml.target!
+ end
+
def add_credit_card(xml, credit_card)
xml.tag! 'Card' do
xml.tag! 'CardType', credit_card_type(credit_card)
diff --git a/lib/active_merchant/billing/gateways/payment_express.rb b/lib/active_merchant/billing/gateways/payment_express.rb
index 450b26e2661..290c593ca34 100644
--- a/lib/active_merchant/billing/gateways/payment_express.rb
+++ b/lib/active_merchant/billing/gateways/payment_express.rb
@@ -227,7 +227,7 @@ def add_address_verification_data(xml, options)
end
# The options hash may contain optional data which will be passed
- # through the the specialized optional fields at PaymentExpress
+ # through the specialized optional fields at PaymentExpress
# as follows:
#
# {
diff --git a/lib/active_merchant/billing/gateways/paymill.rb b/lib/active_merchant/billing/gateways/paymill.rb
index 12738d5ef78..3192d49ec3a 100644
--- a/lib/active_merchant/billing/gateways/paymill.rb
+++ b/lib/active_merchant/billing/gateways/paymill.rb
@@ -17,27 +17,11 @@ def initialize(options = {})
end
def purchase(money, payment_method, options = {})
- case payment_method
- when String
- purchase_with_token(money, payment_method, options)
- else
- MultiResponse.run do |r|
- r.process { save_card(payment_method) }
- r.process { purchase_with_token(money, r.authorization, options) }
- end
- end
+ action_with_token(:purchase, money, payment_method, options)
end
def authorize(money, payment_method, options = {})
- case payment_method
- when String
- authorize_with_token(money, payment_method, options)
- else
- MultiResponse.run do |r|
- r.process { save_card(payment_method) }
- r.process { authorize_with_token(money, r.authorization, options) }
- end
- end
+ action_with_token(:authorize, money, payment_method, options)
end
def capture(money, authorization, options = {})
@@ -83,7 +67,7 @@ def commit(method, url, parameters=nil)
raw_response = ssl_request(method, "https://api.paymill.com/v2/#{url}", post_data(parameters), headers)
rescue ResponseError => e
parsed = JSON.parse(e.response.body)
- return Response.new(false, parsed['error'], parsed, {})
+ return Response.new(false, response_message(parsed), parsed, {})
end
response_from(raw_response)
@@ -91,13 +75,13 @@ def commit(method, url, parameters=nil)
def response_from(raw_response)
parsed = JSON.parse(raw_response)
-
options = {
:authorization => authorization_from(parsed),
:test => (parsed['mode'] == 'test'),
}
- Response.new(true, 'Transaction approved', parsed, options)
+ succeeded = (parsed['data'] == []) || (parsed['data']['response_code'] == 20000)
+ Response.new(succeeded, response_message(parsed), parsed, options)
end
def authorization_from(parsed_response)
@@ -110,13 +94,24 @@ def authorization_from(parsed_response)
].join(";")
end
+ def action_with_token(action, money, payment_method, options)
+ case payment_method
+ when String
+ self.send("#{action}_with_token", money, payment_method, options)
+ else
+ MultiResponse.run do |r|
+ r.process { save_card(payment_method) }
+ r.process { self.send("#{action}_with_token", money, r.authorization, options) }
+ end
+ end
+ end
+
def purchase_with_token(money, card_token, options)
post = {}
add_amount(post, money, options)
post[:token] = card_token
post[:description] = options[:description]
- post[:client] = options[:customer]
commit(:post, 'transactions', post)
end
@@ -148,17 +143,12 @@ def save_card(credit_card)
def response_for_save_from(raw_response)
options = { :test => test? }
- parsed = JSON.parse(raw_response.sub(/jsonPFunction\(/, '').sub(/\)\z/, ''))
- if parsed['error']
- succeeded = false
- message = parsed['error']['message']
- else
- succeeded = parsed['transaction']['processing']['result'] == 'ACK'
- message = parsed['transaction']['processing']['return']['message']
- options[:authorization] = parsed['transaction']['identification']['uniqueId'] if succeeded
- end
+ parser = ResponseParser.new(raw_response, options)
+ parser.generate_response
+ end
- Response.new(succeeded, message, parsed, options)
+ def parse_reponse(response)
+ JSON.parse(response.sub(/jsonPFunction\(/, '').sub(/\)\z/, ''))
end
def save_card_url
@@ -184,6 +174,99 @@ def preauth(authorization)
def transaction_id(authorization)
authorization.split(';').first
end
+
+ RESPONSE_CODES = {
+ 10001 => "General undefined response.",
+ 10002 => "Still waiting on something.",
+
+ 20000 => "General success response.",
+
+ 40000 => "General problem with data.",
+ 40001 => "General problem with payment data.",
+ 40100 => "Problem with credit card data.",
+ 40101 => "Problem with cvv.",
+ 40102 => "Card expired or not yet valid.",
+ 40103 => "Limit exceeded.",
+ 40104 => "Card invalid.",
+ 40105 => "Expiry date not valid.",
+ 40106 => "Credit card brand required.",
+ 40200 => "Problem with bank account data.",
+ 40201 => "Bank account data combination mismatch.",
+ 40202 => "User authentication failed.",
+ 40300 => "Problem with 3d secure data.",
+ 40301 => "Currency / amount mismatch",
+ 40400 => "Problem with input data.",
+ 40401 => "Amount too low or zero.",
+ 40402 => "Usage field too long.",
+ 40403 => "Currency not allowed.",
+
+ 50000 => "General problem with backend.",
+ 50001 => "Country blacklisted.",
+ 50100 => "Technical error with credit card.",
+ 50101 => "Error limit exceeded.",
+ 50102 => "Card declined by authorization system.",
+ 50103 => "Manipulation or stolen card.",
+ 50104 => "Card restricted.",
+ 50105 => "Invalid card configuration data.",
+ 50200 => "Technical error with bank account.",
+ 50201 => "Card blacklisted.",
+ 50300 => "Technical error with 3D secure.",
+ 50400 => "Decline because of risk issues.",
+ 50500 => "General timeout.",
+ 50501 => "Timeout on side of the acquirer.",
+ 50502 => "Risk management transaction timeout.",
+ 50600 => "Duplicate transaction."
+ }
+
+ def response_message(parsed_response)
+ return parsed_response["error"] if parsed_response["error"]
+ return "Transaction approved." if (parsed_response['data'] == [])
+
+ code = parsed_response["data"]["response_code"]
+ RESPONSE_CODES[code] || code.to_s
+ end
+
+
+ class ResponseParser
+ def initialize(raw_response="", options={})
+ @raw_response = raw_response
+ @options = options
+ end
+
+ def generate_response
+ parse_response
+ if parsed['error']
+ handle_response_parse_error
+ else
+ handle_response_correct_parsing
+ end
+
+ Response.new(succeeded, message, parsed, options)
+ end
+
+ private
+ attr_reader :raw_response, :parsed, :succeeded, :message, :options
+
+ def parse_response
+ @parsed = JSON.parse(raw_response.sub(/jsonPFunction\(/, '').sub(/\)\z/, ''))
+ end
+
+ def handle_response_parse_error
+ @succeeded = false
+ @message = parsed['error']['message']
+ end
+
+ def handle_response_correct_parsing
+ @message = parsed['transaction']['processing']['return']['message']
+ if @succeeded = is_ack?
+ @options[:authorization] = parsed['transaction']['identification']['uniqueId']
+ end
+ end
+
+ def is_ack?
+ parsed['transaction']['processing']['result'] == 'ACK'
+ end
+ end
end
end
end
diff --git a/lib/active_merchant/billing/gateways/paypal/paypal_common_api.rb b/lib/active_merchant/billing/gateways/paypal/paypal_common_api.rb
index 74fb4d4c91b..2fad6c2128c 100644
--- a/lib/active_merchant/billing/gateways/paypal/paypal_common_api.rb
+++ b/lib/active_merchant/billing/gateways/paypal/paypal_common_api.rb
@@ -242,7 +242,7 @@ def authorize_transaction(transaction_id, money, options = {})
commit 'DoAuthorization', build_do_authorize(transaction_id, money, options)
end
- # The ManagePendingTransactionStatus API operation accepts or denys a
+ # The ManagePendingTransactionStatus API operation accepts or denies a
# pending transaction held by Fraud Management Filters.
#
# ==== Parameters:
diff --git a/lib/active_merchant/billing/gateways/paypal/paypal_recurring_api.rb b/lib/active_merchant/billing/gateways/paypal/paypal_recurring_api.rb
index 157037cb176..c70308ddd0d 100644
--- a/lib/active_merchant/billing/gateways/paypal/paypal_recurring_api.rb
+++ b/lib/active_merchant/billing/gateways/paypal/paypal_recurring_api.rb
@@ -12,7 +12,7 @@ module PaypalRecurringApi
# This transaction creates a recurring payment profile
# ==== Parameters
#
- # * money -- The amount to be charged to the customer at each interval as an Integer value in cents.
+ # * amount -- The amount to be charged to the customer at each interval as an Integer value in cents.
# * credit_card -- The CreditCard details for the transaction.
# * options -- A hash of parameters.
#
diff --git a/lib/active_merchant/billing/gateways/payscout.rb b/lib/active_merchant/billing/gateways/payscout.rb
new file mode 100644
index 00000000000..b56c391fcce
--- /dev/null
+++ b/lib/active_merchant/billing/gateways/payscout.rb
@@ -0,0 +1,171 @@
+module ActiveMerchant #:nodoc:
+ module Billing #:nodoc:
+ class PayscoutGateway < Gateway
+ self.live_url = self.test_url = 'https://secure.payscout.com/api/transact.php'
+
+ self.supported_countries = ['US']
+ self.supported_cardtypes = [:visa, :master, :american_express, :discover]
+ self.default_currency = 'USD'
+ self.homepage_url = 'http://www.payscout.com/'
+ self.display_name = 'Payscout'
+
+ self.ssl_version = 'SSLv3'
+
+ def initialize(options = {})
+ requires!(options, :username, :password)
+ super
+ end
+
+ def authorize(money, creditcard, options = {})
+ post = {}
+ add_invoice(post, options)
+ add_creditcard(post, creditcard)
+ add_currency(post, money, options)
+ add_address(post, options)
+
+ commit('auth', money, post)
+ end
+
+ def purchase(money, creditcard, options = {})
+ post = {}
+ add_invoice(post, options)
+ add_creditcard(post, creditcard)
+ add_currency(post, money, options)
+ add_address(post, options)
+
+ commit('sale', money, post)
+ end
+
+ def capture(money, authorization, options = {})
+ post = {}
+ post[:transactionid] = authorization
+
+ commit('capture', money, post)
+ end
+
+
+ def refund(money, authorization, options = {})
+ post = {}
+ post[:transactionid] = authorization
+
+ commit('refund', money, post)
+ end
+
+ def void(authorization, options = {})
+ post = {}
+ post[:transactionid] = authorization
+
+ commit('void', nil, post)
+ end
+
+ private
+
+ def add_address(post, options)
+ if address = options[:billing_address] || options[:address]
+ post[:address1] = address[:address1].to_s
+ post[:address2] = address[:address2].to_s
+ post[:city] = address[:city].to_s
+ post[:state] = (address[:state].blank? ? 'n/a' : address[:state])
+ post[:zip] = address[:zip].to_s
+ post[:country] = address[:country].to_s
+ post[:phone] = address[:phone].to_s
+ post[:fax] = address[:fax].to_s
+ post[:email] = address[:email].to_s
+ end
+
+ if address = options[:shipping_address]
+ post[:shipping_firstname] = address[:first_name].to_s
+ post[:shipping_lastname] = address[:last_name].to_s
+ post[:shipping_company] = address[:company].to_s
+ post[:shipping_address1] = address[:address1].to_s
+ post[:shipping_address2] = address[:address2].to_s
+ post[:shipping_city] = address[:city].to_s
+ post[:shipping_country] = address[:country].to_s
+ post[:shipping_state] = (address[:state].blank? ? 'n/a' : address[:state])
+ post[:shipping_zip] = address[:zip].to_s
+ post[:shipping_email] = address[:email].to_s
+ end
+ end
+
+ def add_currency(post, money, options)
+ post[:currency] = options[:currency] || currency(money)
+ end
+
+ def add_invoice(post, options)
+ post[:orderdescription] = options[:description]
+ post[:orderid] = options[:order_id]
+ end
+
+ def add_creditcard(post, creditcard)
+ post[:ccnumber] = creditcard.number
+ post[:cvv] = creditcard.verification_value if creditcard.verification_value?
+ post[:ccexp] = expdate(creditcard)
+ post[:firstname] = creditcard.first_name
+ post[:lastname] = creditcard.last_name
+ end
+
+ def parse(body)
+ Hash[body.split('&').map{|x|x.split('=')}]
+ end
+
+ def commit(action, money, parameters)
+ parameters[:amount] = amount(money) unless action == 'void'
+ url = (test? ? self.test_url : self.live_url)
+ data = ssl_post(url, post_data(action, parameters))
+
+ response = parse(data)
+ response[:action] = action
+
+ message = message_from(response)
+ test_mode = (test? || message =~ /TESTMODE/)
+ Response.new(success?(response), message, response,
+ :test => test_mode,
+ :authorization => response['transactionid'],
+ :fraud_review => fraud_review?(response),
+ :avs_result => { :code => response['avsresponse'] },
+ :cvv_result => response['cvvresponse']
+ )
+ end
+
+ def message_from(response)
+ case response['response']
+ when '1'
+ 'The transaction has been approved'
+ when '2'
+ 'The transaction has been declined'
+ when '3'
+ response['responsetext']
+ else
+ 'There was an error processing the transaction'
+ end
+ end
+
+ def fraud_review?(response)
+ false
+ end
+
+ def success?(response)
+ (response['response'] == '1')
+ end
+
+ def post_data(action, parameters = {})
+ post = {}
+
+ post[:username] = @options[:username]
+ post[:password] = @options[:password]
+ post[:type] = action
+
+ request = post.merge(parameters).collect { |key, value| "#{key}=#{URI.escape(value.to_s)}" }.join("&")
+ request
+ end
+
+ def expdate(creditcard)
+ year = sprintf("%.4i", creditcard.year)
+ month = sprintf("%.2i", creditcard.month)
+
+ "#{month}#{year[-2..-1]}"
+ end
+ end
+ end
+end
+
diff --git a/lib/active_merchant/billing/gateways/pin.rb b/lib/active_merchant/billing/gateways/pin.rb
index 8e1c2ffd0be..26e7cce06b2 100644
--- a/lib/active_merchant/billing/gateways/pin.rb
+++ b/lib/active_merchant/billing/gateways/pin.rb
@@ -90,7 +90,7 @@ def add_creditcard(post, creditcard)
:expiry_month => creditcard.month,
:expiry_year => creditcard.year,
:cvc => creditcard.verification_value,
- :name => "#{creditcard.first_name} #{creditcard.last_name}"
+ :name => creditcard.name
)
elsif creditcard.kind_of?(String)
if creditcard =~ /^card_/
diff --git a/lib/active_merchant/billing/gateways/realex.rb b/lib/active_merchant/billing/gateways/realex.rb
index 06ebdabb0c5..f4404710e7f 100644
--- a/lib/active_merchant/billing/gateways/realex.rb
+++ b/lib/active_merchant/billing/gateways/realex.rb
@@ -12,7 +12,7 @@ module Billing
# login - The unique id of the merchant
# password - The secret is used to digitally sign the request
# account - This is an optional third part of the authentication process
- # and is used if the merchant wishes do distuinguish cc traffic from the different sources
+ # and is used if the merchant wishes do distinguish cc traffic from the different sources
# by using a different account. This must be created in advance
#
# the Realex team decided to make the orderid unique per request,
diff --git a/lib/active_merchant/billing/gateways/redsys.rb b/lib/active_merchant/billing/gateways/redsys.rb
index 583e025393c..114a3ca7d4e 100644
--- a/lib/active_merchant/billing/gateways/redsys.rb
+++ b/lib/active_merchant/billing/gateways/redsys.rb
@@ -49,7 +49,7 @@ class RedsysGateway < Gateway
self.default_currency = 'EUR'
self.money_format = :cents
- # Not all card types may be actived by the bank!
+ # Not all card types may be activated by the bank!
self.supported_cardtypes = [:visa, :master, :american_express, :jcb, :diners_club]
# Homepage URL of the gateway for reference
diff --git a/lib/active_merchant/billing/gateways/secure_pay_au.rb b/lib/active_merchant/billing/gateways/secure_pay_au.rb
index dd552114edb..db05999c1a8 100644
--- a/lib/active_merchant/billing/gateways/secure_pay_au.rb
+++ b/lib/active_merchant/billing/gateways/secure_pay_au.rb
@@ -108,8 +108,10 @@ def unstore(identification, options = {})
def build_purchase_request(money, credit_card, options)
xml = Builder::XmlMarkup.new
- xml.tag! 'amount', amount(money)
- xml.tag! 'currency', options[:currency] || currency(money)
+ currency = options[:currency] || currency(money)
+
+ xml.tag! 'amount', localized_amount(money, currency)
+ xml.tag! 'currency', currency
xml.tag! 'purchaseOrderNo', options[:order_id].to_s.gsub(/[ ']/, '')
xml.tag! 'CreditCardInfo' do
diff --git a/lib/active_merchant/billing/gateways/so_easy_pay.rb b/lib/active_merchant/billing/gateways/so_easy_pay.rb
new file mode 100644
index 00000000000..2227a74ebe4
--- /dev/null
+++ b/lib/active_merchant/billing/gateways/so_easy_pay.rb
@@ -0,0 +1,194 @@
+module ActiveMerchant #:nodoc:
+ module Billing #:nodoc:
+ class SoEasyPayGateway < Gateway
+ self.live_url = self.test_url = 'https://secure.soeasypay.com/gateway.asmx'
+ self.money_format = :cents
+
+ self.supported_countries = [
+ 'US', 'CA', 'AT', 'BE', 'BG', 'HR', 'CY', 'CZ', 'DK', 'EE',
+ 'FI', 'FR', 'DE', 'GR', 'HU', 'IE', 'IT', 'LV', 'LT', 'LU',
+ 'MT', 'NL', 'PL', 'PT', 'RO', 'SK', 'SI', 'ES', 'SE', 'GB',
+ 'IS', 'NO', 'CH'
+ ]
+ self.supported_cardtypes = [:visa, :master, :american_express, :discover, :maestro, :jcb, :solo, :diners_club]
+ self.homepage_url = 'http://www.soeasypay.com/'
+ self.display_name = 'SoEasyPay'
+
+ def initialize(options = {})
+ requires!(options, :login, :password)
+ super
+ end
+
+ def authorize(money, payment_source, options = {})
+ if payment_source.respond_to?(:number)
+ commit('AuthorizeTransaction', do_authorization(money, payment_source, options), options)
+ else
+ commit('ReauthorizeTransaction', do_reauthorization(money, payment_source, options), options)
+ end
+ end
+
+ def purchase(money, payment_source, options = {})
+ if payment_source.respond_to?(:number)
+ commit('SaleTransaction', do_sale(money, payment_source, options), options)
+ else
+ commit('RebillTransaction', do_rebill(money, payment_source, options), options)
+ end
+ end
+
+ def capture(money, authorization, options = {})
+ commit('CaptureTransaction', do_capture(money, authorization, options), options)
+ end
+
+ def refund(money, authorization, options={})
+ commit('RefundTransaction', do_refund(money, authorization, options), options)
+ end
+
+ def void(authorization, options={})
+ commit('CancelTransaction', do_void(authorization, options), options)
+ end
+
+ private
+
+ def do_authorization(money, card, options)
+ build_soap('AuthorizeTransaction') do |soap|
+ fill_credentials(soap, options)
+ fill_order_info(soap, money, options)
+ fill_cardholder(soap, card, options)
+ fill_card(soap, card)
+ end
+ end
+
+ def do_sale(money, card, options)
+ build_soap('SaleTransaction') do |soap|
+ fill_credentials(soap, options)
+ fill_order_info(soap, money, options)
+ fill_cardholder(soap, card, options)
+ fill_card(soap, card)
+ end
+ end
+
+ def do_reauthorization(money, authorization, options)
+ build_soap('ReauthorizeTransaction') do |soap|
+ fill_credentials(soap, options)
+ fill_order_info(soap, money, options)
+ fill_transaction_id(soap, authorization)
+ end
+ end
+
+ def do_rebill(money, authorization, options)
+ build_soap('RebillTransaction') do |soap|
+ fill_credentials(soap, options)
+ fill_order_info(soap, money, options)
+ fill_transaction_id(soap, authorization)
+ end
+ end
+
+ def do_capture(money, authorization, options)
+ build_soap('CaptureTransaction') do |soap|
+ fill_credentials(soap, options)
+ fill_order_info(soap, money, options, :no_currency)
+ fill_transaction_id(soap, authorization)
+ end
+ end
+
+ def do_refund(money, authorization, options)
+ build_soap('RefundTransaction') do |soap|
+ fill_credentials(soap, options)
+ fill_order_info(soap, money, options, :no_currency)
+ fill_transaction_id(soap, authorization)
+ end
+ end
+
+ def do_void(authorization, options)
+ build_soap('CancelTransaction') do |soap|
+ fill_credentials(soap, options)
+ fill_transaction_id(soap, authorization)
+ end
+ end
+
+ def fill_credentials(soap, options)
+ soap.tag!('websiteID', @options[:login].to_s)
+ soap.tag!('password', @options[:password].to_s)
+ end
+
+ def fill_cardholder(soap, card, options)
+ ch_info = options[:billing_address] || options[:address]
+
+ soap.tag!('customerIP',options[:ip].to_s)
+ name = card.name || ch_info[:name]
+ soap.tag!('cardHolderName', name.to_s)
+ address = ch_info[:address1] || ''
+ address << ch_info[:address2] if ch_info[:address2]
+ soap.tag!('cardHolderAddress', address.to_s)
+ soap.tag!('cardHolderZipcode', ch_info[:zip].to_s)
+ soap.tag!('cardHolderCity', ch_info[:city].to_s)
+ soap.tag!('cardHolderState', ch_info[:state].to_s)
+ soap.tag!('cardHolderCountryCode', ch_info[:country].to_s)
+ soap.tag!('cardHolderPhone', ch_info[:phone].to_s)
+ soap.tag!('cardHolderEmail', options[:email].to_s)
+ end
+
+ def fill_transaction_id(soap, transaction_id)
+ soap.tag!('transactionID', transaction_id.to_s)
+ end
+
+ def fill_card(soap, card)
+ soap.tag!('cardNumber', card.number.to_s)
+ soap.tag!('cardSecurityCode', card.verification_value.to_s)
+ soap.tag!('cardExpireMonth', card.month.to_s.rjust(2, "0"))
+ soap.tag!('cardExpireYear', card.year.to_s)
+ end
+
+ def fill_order_info(soap, money, options, skip_currency=false)
+ soap.tag!('orderID', options[:order_id].to_s)
+ soap.tag!('orderDescription', "Order #{options[:order_id]}")
+ soap.tag!('amount', amount(money).to_s)
+ soap.tag!('currency', (options[:currency] || currency(money)).to_s) unless skip_currency
+ end
+
+ def parse(response, action)
+ result = {}
+ document = REXML::Document.new(response)
+ response_element = document.root.get_elements("//[@xsi:type='tns:#{action}Response']").first
+ response_element.elements.each do |element|
+ result[element.name.underscore] = element.text
+ end
+ result
+ end
+
+ def commit(soap_action, soap, options)
+ headers = {"SOAPAction" => "\"urn:Interface##{soap_action}\"",
+ "Content-Type" => "text/xml; charset=utf-8"}
+ response_string = ssl_post(test? ? self.test_url : self.live_url, soap, headers)
+ response = parse(response_string, soap_action)
+ return Response.new(response['errorcode'] == '000',
+ response['errormessage'],
+ response,
+ :test => test?,
+ :authorization => response['transaction_id'])
+ end
+
+ def build_soap(request)
+ retval = Builder::XmlMarkup.new(:indent => 2)
+ retval.instruct!(:xml, :version => '1.0', :encoding => 'utf-8')
+ retval.tag!('soap:Envelope', {
+ 'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
+ 'xmlns:xsd' => 'http://www.w3.org/2001/XMLSchema',
+ 'xmlns:soapenc' => 'http://schemas.xmlsoap.org/soap/encoding/',
+ 'xmlns:tns' => 'urn:Interface',
+ 'xmlns:types' => 'urn:Interface/encodedTypes',
+ 'xmlns:soap' => 'http://schemas.xmlsoap.org/soap/envelope/'}) do
+ retval.tag!('soap:Body', {'soap:encodingStyle'=>'http://schemas.xmlsoap.org/soap/encoding/'}) do
+ retval.tag!("tns:#{request}") do
+ retval.tag!("#{request}Request", {'xsi:type'=>"tns:#{request}Request"}) do
+ yield retval
+ end
+ end
+ end
+ end
+ retval.target!
+ end
+
+ end
+ end
+end
diff --git a/lib/active_merchant/billing/gateways/spreedly_core.rb b/lib/active_merchant/billing/gateways/spreedly_core.rb
index bc1e50505ba..5f26aa80808 100644
--- a/lib/active_merchant/billing/gateways/spreedly_core.rb
+++ b/lib/active_merchant/billing/gateways/spreedly_core.rb
@@ -93,7 +93,8 @@ def void(authorization, options={})
# credit_card - The CreditCard to store
# options - A standard ActiveMerchant options hash
def store(credit_card, options={})
- save_card(true, credit_card, options)
+ retain = (options.has_key?(:retain) ? options[:retain] : true)
+ save_card(retain, credit_card, options)
end
# Public: Redact the CreditCard in Spreedly. This wipes the sensitive
@@ -118,7 +119,7 @@ def save_card(retain, credit_card, options)
def purchase_with_token(money, payment_method_token, options)
request = auth_purchase_request(money, payment_method_token, options)
- commit("gateways/#{@options[:gateway_token]}/purchase.xml", request)
+ commit("gateways/#{options[:gateway_token] || @options[:gateway_token]}/purchase.xml", request)
end
def authorize_with_token(money, payment_method_token, options)
@@ -137,6 +138,7 @@ def auth_purchase_request(money, payment_method_token, options)
def add_invoice(doc, money, options)
doc.amount amount(money)
doc.currency_code(options[:currency] || currency(money) || default_currency)
+ doc.order_id(options[:order_id])
end
def add_credit_card(doc, credit_card, options)
diff --git a/lib/active_merchant/billing/gateways/stripe.rb b/lib/active_merchant/billing/gateways/stripe.rb
index 0e06a2bd4d9..cf2af37b42c 100644
--- a/lib/active_merchant/billing/gateways/stripe.rb
+++ b/lib/active_merchant/billing/gateways/stripe.rb
@@ -40,7 +40,7 @@ def authorize(money, creditcard, options = {})
post = create_post_for_auth_or_purchase(money, creditcard, options)
post[:capture] = "false"
- commit(:post, 'charges', post, generate_meta(options))
+ commit(:post, 'charges', post, generate_options(options))
end
# To create a charge on a card or a token, call
@@ -53,7 +53,7 @@ def authorize(money, creditcard, options = {})
def purchase(money, creditcard, options = {})
post = create_post_for_auth_or_purchase(money, creditcard, options)
- commit(:post, 'charges', post, generate_meta(options))
+ commit(:post, 'charges', post, generate_options(options))
end
def capture(money, authorization, options = {})
@@ -69,7 +69,7 @@ def void(identification, options = {})
def refund(money, identification, options = {})
post = {:amount => amount(money)}
- commit_options = generate_meta(options)
+ commit_options = generate_options(options)
MultiResponse.run(:first) do |r|
r.process { commit(:post, "charges/#{CGI.escape(identification)}/refund", post, commit_options) }
@@ -97,28 +97,42 @@ def refund_application_fee(money, identification, options = {})
commit(:post, "application_fees/#{CGI.escape(identification)}/refund", post, options)
end
+ # Note: creating a new credit card will not change the customer's existing default credit card (use :set_default => true)
def store(creditcard, options = {})
post = {}
add_creditcard(post, creditcard, options)
post[:description] = options[:description]
post[:email] = options[:email]
- path = if options[:customer]
- "customers/#{CGI.escape(options[:customer])}"
+ commit_options = generate_options(options)
+ if options[:customer]
+ MultiResponse.run(:first) do |r|
+ r.process { commit(:post, "customers/#{CGI.escape(options[:customer])}/cards", post, commit_options) }
+
+ return r unless options[:set_default] and r.success? and !r.params["id"].blank?
+
+ r.process { update_customer(options[:customer], :default_card => r.params["id"]) }
+ end
else
- 'customers'
+ commit(:post, 'customers', post, commit_options)
end
-
- commit(:post, path, post, generate_meta(options))
end
def update(customer_id, creditcard, options = {})
- options = options.merge(:customer => customer_id)
+ options = options.merge(:customer => customer_id, :set_default => true)
store(creditcard, options)
end
- def unstore(customer_id, options = {})
- commit(:delete, "customers/#{CGI.escape(customer_id)}", nil, generate_meta(options))
+ def update_customer(customer_id, options = {})
+ commit(:post, "customers/#{CGI.escape(customer_id)}", options, generate_options(options))
+ end
+
+ def unstore(customer_id, card_id = nil, options = {})
+ if card_id.nil?
+ commit(:delete, "customers/#{CGI.escape(customer_id)}", nil, generate_options(options))
+ else
+ commit(:delete, "customers/#{CGI.escape(customer_id)}/cards/#{CGI.escape(card_id)}", nil, generate_options(options))
+ end
end
private
@@ -127,9 +141,10 @@ def create_post_for_auth_or_purchase(money, creditcard, options)
post = {}
add_amount(post, money, options)
add_creditcard(post, creditcard, options)
- add_customer(post, options)
+ add_customer(post, creditcard, options)
add_customer_data(post,options)
- post[:description] = options[:description] || options[:email]
+ post[:description] = options[:description]
+ post[:metadata] = { email: options[:email] } if options[:email]
add_flags(post, options)
add_application_fee(post, options)
post
@@ -145,7 +160,7 @@ def add_application_fee(post, options)
end
def add_customer_data(post, options)
- metadata_options = [:description,:browser_ip,:user_agent,:referrer]
+ metadata_options = [:description, :ip, :user_agent, :referrer]
post.update(options.slice(*metadata_options))
post[:external_id] = options[:order_id]
@@ -189,8 +204,8 @@ def add_creditcard(post, creditcard, options)
end
end
- def add_customer(post, options)
- post[:customer] = options[:customer] if options[:customer]
+ def add_customer(post, creditcard, options)
+ post[:customer] = options[:customer] if options[:customer] && !creditcard.respond_to?(:number)
end
def add_flags(post, options)
@@ -224,6 +239,11 @@ def post_data(params)
end.compact.join("&")
end
+ def generate_options(raw_options)
+ options = generate_meta(raw_options)
+ options.merge!(raw_options.slice(:version, :key))
+ end
+
def generate_meta(options)
{:meta => {:ip => options[:ip]}}
end
@@ -234,18 +254,19 @@ def headers(options = {})
:lang => 'ruby',
:lang_version => "#{RUBY_VERSION} p#{RUBY_PATCHLEVEL} (#{RUBY_RELEASE_DATE})",
:platform => RUBY_PLATFORM,
- :publisher => 'active_merchant',
- :uname => (RUBY_PLATFORM =~ /linux|darwin/i ? `uname -a 2>/dev/null`.strip : nil)
+ :publisher => 'active_merchant'
})
key = options[:key] || @api_key
- {
+ headers = {
"Authorization" => "Basic " + Base64.encode64(key.to_s + ":").strip,
"User-Agent" => "Stripe/v1 ActiveMerchantBindings/#{ActiveMerchant::VERSION}",
"X-Stripe-Client-User-Agent" => @@ua,
"X-Stripe-Client-User-Metadata" => options[:meta].to_json
}
+ headers.merge!("Stripe-Version" => options[:version]) if options[:version]
+ headers
end
def commit(method, url, parameters=nil, options = {})
diff --git a/lib/active_merchant/billing/gateways/swipe_checkout.rb b/lib/active_merchant/billing/gateways/swipe_checkout.rb
new file mode 100644
index 00000000000..df235de2ad1
--- /dev/null
+++ b/lib/active_merchant/billing/gateways/swipe_checkout.rb
@@ -0,0 +1,158 @@
+require 'json'
+
+module ActiveMerchant #:nodoc:
+ module Billing #:nodoc:
+ class SwipeCheckoutGateway < Gateway
+ TRANSACTION_APPROVED_MSG = 'Transaction approved'
+ TRANSACTION_DECLINED_MSG = 'Transaction declined'
+
+ LIVE_URLS = {
+ 'NZ' => 'https://api.swipehq.com',
+ 'CA' => 'https://api.swipehq.ca'
+ }
+ self.test_url = 'https://api.swipehq.com'
+
+ TRANSACTION_API = '/createShopifyTransaction.php'
+
+ self.supported_countries = %w[ NZ CA ]
+ self.default_currency = 'NZD'
+ self.supported_cardtypes = [:visa, :master]
+ self.homepage_url = 'https://www.swipehq.com/checkout'
+ self.display_name = 'Swipe Checkout'
+ self.money_format = :dollars
+
+ # Swipe Checkout requires the merchant's email and API key for authorization.
+ # This can be found under Settings > API Credentials after logging in to your
+ # Swipe Checkout merchant console at https://merchant.swipehq.[com|ca]
+ #
+ # :region determines which Swipe URL is used, this can be one of "NZ" or "CA".
+ # Currently Swipe Checkout has New Zealand and Canadian domains (swipehq.com
+ # and swipehq.ca respectively). Merchants must use the region that they
+ # signed up in for authentication with their merchant ID and API key to succeed.
+ def initialize(options = {})
+ requires!(options, :login, :api_key, :region)
+ super
+ end
+
+ # Transfers funds immediately.
+ # Note that Swipe Checkout only supports purchase at this stage
+ def purchase(money, creditcard, options = {})
+ post = {}
+ add_invoice(post, options)
+ add_creditcard(post, creditcard)
+ add_customer_data(post, creditcard, options)
+ add_amount(post, money, options)
+
+ commit('sale', money, post)
+ end
+
+ private
+
+ def add_customer_data(post, creditcard, options)
+ post[:email] = options[:email]
+ post[:ip_address] = options[:ip]
+
+ address = options[:billing_address] || options[:address]
+ return if address.nil?
+
+ post[:company] = address[:company]
+
+ # groups all names after the first into the last name param
+ post[:first_name], post[:last_name] = address[:name].split(' ', 2)
+ post[:address] = "#{address[:address1]}, #{address[:address2]}"
+ post[:city] = address[:city]
+ post[:country] = address[:country]
+ post[:mobile] = address[:phone] # API only has a "mobile" field, no "phone"
+ end
+
+ def add_invoice(post, options)
+ # store shopping-cart order ID in Swipe for merchant's records
+ post[:td_user_data] = options[:order_id] if options[:order_id]
+ post[:td_item] = options[:description] if options[:description]
+ post[:td_description] = options[:description] if options[:description]
+ post[:item_quantity] = "1"
+ end
+
+ def add_creditcard(post, creditcard)
+ post[:card_number] = creditcard.number
+ post[:card_type] = creditcard.brand
+ post[:name_on_card] = "#{creditcard.first_name} #{creditcard.last_name}"
+ post[:card_expiry] = expdate(creditcard)
+ post[:secure_number] = creditcard.verification_value
+ end
+
+ def expdate(creditcard)
+ year = format(creditcard.year, :two_digits)
+ month = format(creditcard.month, :two_digits)
+
+ "#{month}#{year}"
+ end
+
+ def add_amount(post, money, options)
+ post[:amount] = money.to_s
+
+ post[:currency] = (options[:currency] || currency(money))
+ end
+
+ def commit(action, money, parameters)
+ case action
+ when "sale"
+ begin
+ response = call_api(TRANSACTION_API, parameters)
+
+ # response code and message params should always be present
+ code = response["response_code"]
+ message = response["message"]
+
+ if code == 200
+ result = response["data"]["result"]
+ success = (result == 'accepted' || (test? && result == 'test-accepted'))
+
+ Response.new(success,
+ success ?
+ TRANSACTION_APPROVED_MSG :
+ TRANSACTION_DECLINED_MSG,
+ response,
+ :test => test?
+ )
+ else
+ build_error_response(message, response)
+ end
+ rescue ResponseError => e
+ raw_response = e.response.body
+ build_error_response("ssl_post() with url #{url} raised ResponseError: #{e}")
+ rescue JSON::ParserError => e
+ msg = 'Invalid response received from the Swipe Checkout API. ' +
+ 'Please contact support@optimizerhq.com if you continue to receive this message.' +
+ " (Full error message: #{e})"
+ build_error_response(msg)
+ end
+ end
+ end
+
+ def call_api(api, params=nil)
+ params ||= {}
+ params[:merchant_id] = @options[:login]
+ params[:api_key] = @options[:api_key]
+
+ # ssl_post() returns the response body as a string on success,
+ # or raises a ResponseError exception on failure
+ JSON.parse(ssl_post(url(@options[:region], api), params.to_query))
+ end
+
+ def url(region, api)
+ ((test? ? self.test_url : LIVE_URLS[region]) + api)
+ end
+
+ def build_error_response(message, params={})
+ Response.new(
+ false,
+ message,
+ params,
+ :test => test?
+ )
+ end
+ end
+ end
+end
+
diff --git a/lib/active_merchant/billing/gateways/usa_epay_advanced.rb b/lib/active_merchant/billing/gateways/usa_epay_advanced.rb
index 6b3faeb312b..acd48e2b367 100644
--- a/lib/active_merchant/billing/gateways/usa_epay_advanced.rb
+++ b/lib/active_merchant/billing/gateways/usa_epay_advanced.rb
@@ -179,7 +179,6 @@ class UsaEpayAdvancedGateway < Gateway
} #:nodoc:
CHECK_DATA_OPTIONS = {
- :check_number => [:integer, 'CheckNumber'],
:drivers_license => [:string, 'DriversLicense'],
:drivers_license_state => [:string, 'DriversLicenseState'],
:record_type => [:string, 'RecordType'],
@@ -339,9 +338,10 @@ def add_customer(options={})
commit(__method__, request)
end
- # Update a customer by replacing all of the customer details..
+ # Update a customer by replacing all of the customer details.
#
- # Use quickUpdateCustomer to just update a few attributes.
+ # ==== Required
+ # * :customer_number -- customer to update
#
# ==== Options
# * Same as add_customer
@@ -355,7 +355,7 @@ def update_customer(options={})
# Enable a customer for recurring billing.
#
- # Note: Customer does not need to have all recurring paramerters to succeed.
+ # Note: Customer does not need to have all recurring parameters to succeed.
#
# ==== Required
# * :customer_number
@@ -454,7 +454,7 @@ def update_customer_payment_method(options={})
commit(__method__, request)
end
- # Delete one the payment methods beloning to a customer
+ # Delete one the payment methods belonging to a customer
#
# ==== Required
# * :customer_number
@@ -543,11 +543,11 @@ def run_customer_transaction(options={})
# will be returned in the response.
#
# ==== Options
- # * :method -- credit_card or check
+ # * :payment_method -- credit_card or check
# * :command -- sale, credit, void, creditvoid, authonly, capture, postauth, check, checkcredit; defaults to sale; only required for run_transaction when other than sale
# * :reference_number -- for the original transaction; obtained by sale or authonly
# * :authorization_code -- required for postauth; obtained offline
- # * :ignore_duplicate -- set +true+ if you want to override the duplicate tranaction handling
+ # * :ignore_duplicate -- set +true+ if you want to override the duplicate transaction handling
# * :account_holder -- name of account holder
# * :customer_id -- merchant assigned id
# * :customer_receipt -- set +true+ to email receipt to billing email address
@@ -680,7 +680,7 @@ def refund_transaction(options={})
commit(__method__, request)
end
- # Override transaction flagged for mananager approval.
+ # Override transaction flagged for manager approval.
#
# Note: Checks only!
#
@@ -1166,7 +1166,7 @@ def build_capture_transaction(soap, options)
soap.tag! "ns1:captureTransaction" do |soap|
build_token soap, options
build_tag soap, :integer, 'RefNum', options[:reference_number]
- build_tag soap, :double, 'RefNum', amount(options[:amount])
+ build_tag soap, :double, 'Amount', amount(options[:amount])
end
end
@@ -1244,16 +1244,18 @@ def build_credit_card_or_check(soap, payment_method)
when payment_method[:method].kind_of?(ActiveMerchant::Billing::CreditCard)
build_tag soap, :string, 'CardNumber', payment_method[:method].number
build_tag soap, :string, 'CardExpiration',
- "#{"%02d" % payment_method[:method].month}#{payment_method[:method].year}"
+ "#{"%02d" % payment_method[:method].month}#{payment_method[:method].year.to_s[-2..-1]}"
if options[:billing_address]
build_tag soap, :string, 'AvsStreet', options[:billing_address][:address1]
build_tag soap, :string, 'AvsZip', options[:billing_address][:zip]
end
build_tag soap, :string, 'CardCode', payment_method[:method].verification_value
when payment_method[:method].kind_of?(ActiveMerchant::Billing::Check)
- build_tag soap, :string, 'Account', payment_method[:method].number
+ build_tag soap, :string, 'Account', payment_method[:method].account_number
build_tag soap, :string, 'Routing', payment_method[:method].routing_number
- build_tag soap, :string, 'AccountType', payment_method[:method].account_type.capitalize
+ unless payment_method[:method].account_type.nil?
+ build_tag soap, :string, 'AccountType', payment_method[:method].account_type.capitalize
+ end
build_tag soap, :string, 'DriversLicense', options[:drivers_license]
build_tag soap, :string, 'DriversLicenseState', options[:drivers_license_state]
build_tag soap, :string, 'RecordType', options[:record_type]
@@ -1323,8 +1325,7 @@ def build_transaction_detail(soap, options)
def build_credit_card_data(soap, options)
soap.CreditCardData 'xsi:type' => "ns1:CreditCardData" do |soap|
build_tag soap, :string, 'CardNumber', options[:payment_method].number
- build_tag soap, :string, 'CardExpiration',
- "#{"%02d" % options[:payment_method].month}#{options[:payment_method].year}"
+ build_tag soap, :string, 'CardExpiration', build_card_expiration(options)
if options[:billing_address]
build_tag soap, :string, 'AvsStreet', options[:billing_address][:address1]
build_tag soap, :string, 'AvsZip', options[:billing_address][:zip]
@@ -1337,8 +1338,17 @@ def build_credit_card_data(soap, options)
end
end
+ def build_card_expiration(options)
+ month = options[:payment_method].month
+ year = options[:payment_method].year
+ unless month.nil? || year.nil?
+ "#{"%02d" % month}#{year.to_s[-2..-1]}"
+ end
+ end
+
def build_check_data(soap, options)
soap.CheckData 'xsi:type' => "ns1:CheckData" do |soap|
+ build_tag soap, :integer, 'CheckNumber', options[:payment_method].number
build_tag soap, :string, 'Account', options[:payment_method].account_number
build_tag soap, :string, 'Routing', options[:payment_method].routing_number
build_tag soap, :string, 'AccountType', options[:payment_method].account_type.capitalize
@@ -1461,7 +1471,8 @@ def parse(action, soap)
when :get_customer_payment_methods
p['item']
when :get_transaction_custom
- p['item'].inject({}) { |map, field| map[field['field']] = field['value']; map }
+ items = p['item'].kind_of?(Array) ? p['item'] : [p['item']]
+ items.inject({}) { |hash, item| hash[item['field']] = item['value']; hash }
else
p
end
diff --git a/lib/active_merchant/billing/gateways/usa_epay_transaction.rb b/lib/active_merchant/billing/gateways/usa_epay_transaction.rb
index 8e5ec3e230c..67eb4ab3330 100644
--- a/lib/active_merchant/billing/gateways/usa_epay_transaction.rb
+++ b/lib/active_merchant/billing/gateways/usa_epay_transaction.rb
@@ -2,20 +2,20 @@ module ActiveMerchant #:nodoc:
module Billing #:nodoc:
class UsaEpayTransactionGateway < Gateway
- self.test_url = 'https://sandbox.usaepay.com/gate.php'
- self.live_url = 'https://www.usaepay.com/gate.php'
+ self.live_url = 'https://www.usaepay.com/gate'
+ self.test_url = 'https://sandbox.usaepay.com/gate'
- self.supported_cardtypes = [:visa, :master, :american_express]
- self.supported_countries = ['US']
- self.homepage_url = 'http://www.usaepay.com/'
- self.display_name = 'USA ePay'
+ self.supported_cardtypes = [:visa, :master, :american_express]
+ self.supported_countries = ['US']
+ self.homepage_url = 'http://www.usaepay.com/'
+ self.display_name = 'USA ePay'
TRANSACTIONS = {
- :authorization => 'authonly',
- :purchase => 'sale',
- :capture => 'capture',
- :refund => 'refund',
- :void => 'void'
+ :authorization => 'cc:authonly',
+ :purchase => 'cc:sale',
+ :capture => 'cc:capture',
+ :refund => 'cc:refund',
+ :void => 'cc:void'
}
def initialize(options = {})
@@ -31,6 +31,7 @@ def authorize(money, credit_card, options = {})
add_credit_card(post, credit_card)
add_address(post, credit_card, options)
add_customer_data(post, options)
+ add_split_payments(post, options)
commit(:authorization, post)
end
@@ -43,6 +44,7 @@ def purchase(money, credit_card, options = {})
add_credit_card(post, credit_card)
add_address(post, credit_card, options)
add_customer_data(post, options)
+ add_split_payments(post, options)
commit(:purchase, post)
end
@@ -66,7 +68,7 @@ def void(authorization, options = {})
commit(:void, post)
end
- private
+ private
def add_amount(post, money)
post[:amount] = amount(money)
@@ -108,16 +110,16 @@ def add_address(post, credit_card, options)
def add_address_for_type(type, post, credit_card, address)
prefix = address_key_prefix(type)
- post[address_key(prefix, 'fname')] = credit_card.first_name
- post[address_key(prefix, 'lname')] = credit_card.last_name
- post[address_key(prefix, 'company')] = address[:company] unless address[:company].blank?
- post[address_key(prefix, 'street')] = address[:address1] unless address[:address1].blank?
- post[address_key(prefix, 'street2')] = address[:address2] unless address[:address2].blank?
- post[address_key(prefix, 'city')] = address[:city] unless address[:city].blank?
- post[address_key(prefix, 'state')] = address[:state] unless address[:state].blank?
- post[address_key(prefix, 'zip')] = address[:zip] unless address[:zip].blank?
- post[address_key(prefix, 'country')] = address[:country] unless address[:country].blank?
- post[address_key(prefix, 'phone')] = address[:phone] unless address[:phone].blank?
+ post[address_key(prefix, 'fname')] = credit_card.first_name
+ post[address_key(prefix, 'lname')] = credit_card.last_name
+ post[address_key(prefix, 'company')] = address[:company] unless address[:company].blank?
+ post[address_key(prefix, 'street')] = address[:address1] unless address[:address1].blank?
+ post[address_key(prefix, 'street2')] = address[:address2] unless address[:address2].blank?
+ post[address_key(prefix, 'city')] = address[:city] unless address[:city].blank?
+ post[address_key(prefix, 'state')] = address[:state] unless address[:state].blank?
+ post[address_key(prefix, 'zip')] = address[:zip] unless address[:zip].blank?
+ post[address_key(prefix, 'country')] = address[:country] unless address[:country].blank?
+ post[address_key(prefix, 'phone')] = address[:phone] unless address[:phone].blank?
end
def address_key_prefix(type)
@@ -132,15 +134,29 @@ def address_key(prefix, key)
end
def add_invoice(post, options)
- post[:invoice] = options[:order_id]
- post[:description] = options[:description]
+ post[:invoice] = options[:order_id]
+ post[:description] = options[:description]
end
def add_credit_card(post, credit_card)
- post[:card] = credit_card.number
- post[:cvv2] = credit_card.verification_value if credit_card.verification_value?
+ post[:card] = credit_card.number
+ post[:cvv2] = credit_card.verification_value if credit_card.verification_value?
post[:expir] = expdate(credit_card)
- post[:name] = credit_card.name
+ post[:name] = credit_card.name
+ end
+
+ # see: http://wiki.usaepay.com/developer/transactionapi#split_payments
+ def add_split_payments(post, options)
+ return unless options[:split_payments].is_a?(Array)
+ options[:split_payments].each_with_index do |payment, index|
+ prefix = '%02d' % (index + 2)
+ post["#{prefix}key"] = payment[:key]
+ post["#{prefix}amount"] = amount(payment[:amount])
+ post["#{prefix}description"] = payment[:description]
+ end
+
+ # When blank it's 'Stop'. 'Continue' is another one
+ post['onError'] = options[:on_error] || 'Void'
end
def parse(body)
@@ -151,32 +167,32 @@ def parse(body)
end
{
- :status => fields['UMstatus'],
- :auth_code => fields['UMauthCode'],
- :ref_num => fields['UMrefNum'],
- :batch => fields['UMbatch'],
- :avs_result => fields['UMavsResult'],
- :avs_result_code => fields['UMavsResultCode'],
- :cvv2_result => fields['UMcvv2Result'],
+ :status => fields['UMstatus'],
+ :auth_code => fields['UMauthCode'],
+ :ref_num => fields['UMrefNum'],
+ :batch => fields['UMbatch'],
+ :avs_result => fields['UMavsResult'],
+ :avs_result_code => fields['UMavsResultCode'],
+ :cvv2_result => fields['UMcvv2Result'],
:cvv2_result_code => fields['UMcvv2ResultCode'],
:vpas_result_code => fields['UMvpasResultCode'],
- :result => fields['UMresult'],
- :error => fields['UMerror'],
- :error_code => fields['UMerrorcode'],
- :acs_url => fields['UMacsurl'],
- :payload => fields['UMpayload']
+ :result => fields['UMresult'],
+ :error => fields['UMerror'],
+ :error_code => fields['UMerrorcode'],
+ :acs_url => fields['UMacsurl'],
+ :payload => fields['UMpayload']
}.delete_if{|k, v| v.nil?}
end
def commit(action, parameters)
- url = (self.test? ? self.test_url : self.live_url)
- response = parse( ssl_post(url, post_data(action, parameters)) )
+ url = (test? ? self.test_url : self.live_url)
+ response = parse(ssl_post(url, post_data(action, parameters)))
Response.new(response[:status] == 'Approved', message_from(response), response,
- :test => test?,
- :authorization => response[:ref_num],
- :cvv_result => response[:cvv2_result_code],
- :avs_result => { :code => response[:avs_result_code] }
+ :test => test?,
+ :authorization => response[:ref_num],
+ :cvv_result => response[:cvv2_result_code],
+ :avs_result => { :code => response[:avs_result_code] }
)
end
@@ -191,7 +207,7 @@ def message_from(response)
def post_data(action, parameters = {})
parameters[:command] = TRANSACTIONS[action]
- parameters[:key] = @options[:login]
+ parameters[:key] = @options[:login]
parameters[:software] = 'Active Merchant'
parameters[:testmode] = (@options[:test] ? 1 : 0)
diff --git a/lib/active_merchant/billing/gateways/webpay.rb b/lib/active_merchant/billing/gateways/webpay.rb
index b08e8aa090f..de8d6e484dc 100644
--- a/lib/active_merchant/billing/gateways/webpay.rb
+++ b/lib/active_merchant/billing/gateways/webpay.rb
@@ -13,12 +13,10 @@ class WebpayGateway < StripeGateway
self.homepage_url = 'https://webpay.jp/'
self.display_name = 'WebPay'
- def authorize(money, credit_card, options = {})
- raise NotImplementedError.new
- end
-
- def capture(money, credit_card, options = {})
- raise NotImplementedError.new
+ def capture(money, authorization, options = {})
+ post = {:amount => localized_amount(money)}
+ add_application_fee(post, options)
+ commit(:post, "charges/#{CGI.escape(authorization)}/capture", post)
end
def refund(money, identification, options = {})
@@ -48,8 +46,28 @@ def add_amount(post, money, options)
post[:amount] = localized_amount(money, post[:currency].upcase)
end
- def add_customer(post, options)
- post[:customer] = options[:customer] if options[:customer] && post[:card].blank?
+ def add_customer(post, creditcard, options)
+ post[:customer] = options[:customer] if options[:customer] && !creditcard.respond_to?(:number)
+ end
+
+ def store(creditcard, options = {})
+ post = {}
+ add_creditcard(post, creditcard, options)
+ post[:description] = options[:description]
+ post[:email] = options[:email]
+
+ commit_options = generate_options(options)
+ if options[:customer]
+ MultiResponse.run(:first) do |r|
+ r.process { commit(:post, "customers/#{CGI.escape(options[:customer])}/", post, commit_options) }
+
+ return r unless options[:set_default] and r.success? and !r.params["id"].blank?
+
+ r.process { update_customer(options[:customer], :default_card => r.params["id"]) }
+ end
+ else
+ commit(:post, 'customers', post, commit_options)
+ end
end
def json_error(raw_response)
@@ -68,8 +86,7 @@ def headers(options = {})
:lang => 'ruby',
:lang_version => "#{RUBY_VERSION} p#{RUBY_PATCHLEVEL} (#{RUBY_RELEASE_DATE})",
:platform => RUBY_PLATFORM,
- :publisher => 'active_merchant',
- :uname => (RUBY_PLATFORM =~ /linux|darwin/i ? `uname -a 2>/dev/null`.strip : nil)
+ :publisher => 'active_merchant'
})
{
diff --git a/lib/active_merchant/billing/gateways/wirecard.rb b/lib/active_merchant/billing/gateways/wirecard.rb
index b1f84d536cc..b448bac75ee 100644
--- a/lib/active_merchant/billing/gateways/wirecard.rb
+++ b/lib/active_merchant/billing/gateways/wirecard.rb
@@ -3,10 +3,7 @@
module ActiveMerchant #:nodoc:
module Billing #:nodoc:
class WirecardGateway < Gateway
- # Test server location
self.test_url = 'https://c3-test.wirecard.com/secure/ssl-gateway'
-
- # Live server location
self.live_url = 'https://c3.wirecard.com/secure/ssl-gateway'
# The Namespaces are not really needed, because it just tells the System, that there's actually no namespace used.
@@ -29,57 +26,51 @@ class WirecardGateway < Gateway
# number 5551234 within area code 202 (country code 1).
VALID_PHONE_FORMAT = /\+\d{1,3}(\(?\d{3}\)?)?\d{3}-\d{4}-\d{3}/
- # The countries the gateway supports merchants from as 2 digit ISO country codes
+ self.supported_cardtypes = [ :visa, :master, :american_express, :diners_club, :jcb, :switch ]
self.supported_countries = %w(AD CY GI IM MT RO CH AT DK GR IT MC SM TR BE EE HU LV NL SK GB BG FI IS LI NO SI VA FR IL LT PL ES CZ DE IE LU PT SE)
-
- # Wirecard supports all major credit and debit cards:
- # Visa, Mastercard, American Express, Diners Club,
- # JCB, Switch, VISA Carte Bancaire, Visa Electron and UATP cards.
- # They also support the latest anti-fraud systems such as Verified by Visa or Master Secure Code.
- self.supported_cardtypes = [
- :visa, :master, :american_express, :diners_club, :jcb, :switch
- ]
-
- # The homepage URL of the gateway
self.homepage_url = 'http://www.wirecard.com'
-
- # The name of the gateway
self.display_name = 'Wirecard'
-
- # The currency should normally be EUROs
self.default_currency = 'EUR'
-
- # 100 is 1.00 Euro
self.money_format = :cents
+ # Public: Create a new Wirecard gateway.
+ #
+ # options - A hash of options:
+ # :login - The username
+ # :password - The password
+ # :signature - The BusinessCaseSignature
def initialize(options = {})
- # verify that username and password are supplied
- requires!(options, :login, :password)
- # unfortunately Wirecard also requires a BusinessCaseSignature in the XML request
- requires!(options, :signature)
+ requires!(options, :login, :password, :signature)
super
end
- # Authorization
def authorize(money, creditcard, options = {})
options[:credit_card] = creditcard
commit(:preauthorization, money, options)
end
- # Capture Authorization
def capture(money, authorization, options = {})
options[:preauthorization] = authorization
commit(:capture, money, options)
end
- # Purchase
def purchase(money, creditcard, options = {})
options[:credit_card] = creditcard
commit(:purchase, money, options)
end
- private
+ def void(identification, options = {})
+ options[:preauthorization] = identification
+ commit(:reversal, nil, options)
+ end
+
+ def refund(money, identification, options = {})
+ options[:preauthorization] = identification
+ commit(:bookback, money, options)
+ end
+
+ private
def prepare_options_hash(options)
result = @options.merge(options)
setup_address_hash!(result)
@@ -156,9 +147,11 @@ def add_transaction_data(xml, money, options)
add_invoice(xml, money, options)
add_creditcard(xml, options[:credit_card])
add_address(xml, options[:billing_address])
- when :capture
+ when :capture, :bookback
xml.tag! 'GuWID', options[:preauthorization]
add_amount(xml, money)
+ when :reversal
+ xml.tag! 'GuWID', options[:preauthorization]
end
end
end
@@ -239,7 +232,7 @@ def parse(xml)
response
end
- # Parse the Element which containts all important information
+ # Parse the Element which contains all important information
def parse_response(response, root)
status = nil
# get the root element for this Transaction
diff --git a/lib/active_merchant/billing/integrations/bit_pay.rb b/lib/active_merchant/billing/integrations/bit_pay.rb
index 53f0b31c39a..f6bd1a21117 100644
--- a/lib/active_merchant/billing/integrations/bit_pay.rb
+++ b/lib/active_merchant/billing/integrations/bit_pay.rb
@@ -1,5 +1,6 @@
require File.dirname(__FILE__) + '/bit_pay/helper.rb'
require File.dirname(__FILE__) + '/bit_pay/notification.rb'
+require File.dirname(__FILE__) + '/bit_pay/return.rb'
module ActiveMerchant #:nodoc:
module Billing #:nodoc:
@@ -12,13 +13,17 @@ module BitPay
mattr_accessor :invoicing_url
self.invoicing_url = 'https://bitpay.com/api/invoice'
- def self.notification(post)
- Notification.new(post)
+ def self.notification(post, options = {})
+ Notification.new(post, options)
end
def self.helper(order, account, options = {})
Helper.new(order, account, options)
end
+
+ def self.return(query_string, options = {})
+ Return.new(query_string)
+ end
end
end
end
diff --git a/lib/active_merchant/billing/integrations/bit_pay/helper.rb b/lib/active_merchant/billing/integrations/bit_pay/helper.rb
index b6753d8cb35..8284022c002 100644
--- a/lib/active_merchant/billing/integrations/bit_pay/helper.rb
+++ b/lib/active_merchant/billing/integrations/bit_pay/helper.rb
@@ -6,20 +6,14 @@ class Helper < ActiveMerchant::Billing::Integrations::Helper
def initialize(order_id, account, options)
super
@account = account
- add_field('orderID', order_id)
- add_field('posData', options[:authcode])
- add_field('currency', options[:currency])
- add_field('fullNotifications', 'true')
- add_field('transactionSpeed', options[:transactionSpeed] || "high")
- add_field('address1', options[:address1])
- generate_invoice_id
+ add_field('posData', {'orderId' => order_id}.to_json)
+ add_field('fullNotifications', true)
+ add_field('transactionSpeed', 'high')
end
- # Replace with the real mapping
mapping :amount, 'price'
-
- mapping :order, 'orderID'
+ mapping :order, 'orderID'
mapping :currency, 'currency'
mapping :customer, :first_name => 'buyerName',
@@ -34,23 +28,23 @@ def initialize(order_id, account, options)
:country => 'buyerCountry'
mapping :notify_url, 'notificationURL'
- mapping :return_url, 'returnURL'
+ mapping :return_url, 'redirectURL'
mapping :id, 'id'
- def generate_invoice_id
- invoice_data = ssl_post(BitPay.invoicing_url)
-
- add_field('id', JSON.parse(invoice_data.body)['id'])
- end
-
def form_method
"GET"
end
+ def form_fields
+ invoice = create_invoice
+
+ {"id" => invoice['id']}
+ end
+
private
- def ssl_post(url, options = {})
- uri = URI.parse(url)
+ def create_invoice
+ uri = URI.parse(BitPay.invoicing_url)
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
@@ -59,7 +53,9 @@ def ssl_post(url, options = {})
request.body = @fields.to_json
request.basic_auth @account, ''
- http.request(request)
+ response = http.request(request)
+ JSON.parse(response.body)
+ rescue JSON::ParserError
end
end
end
diff --git a/lib/active_merchant/billing/integrations/bit_pay/notification.rb b/lib/active_merchant/billing/integrations/bit_pay/notification.rb
index 4aa260347a0..e3e3e7d7999 100644
--- a/lib/active_merchant/billing/integrations/bit_pay/notification.rb
+++ b/lib/active_merchant/billing/integrations/bit_pay/notification.rb
@@ -6,13 +6,29 @@ module Integrations #:nodoc:
module BitPay
class Notification < ActiveMerchant::Billing::Integrations::Notification
def complete?
- status == "complete"
+ status == "Completed"
end
def transaction_id
params['id']
end
+ def item_id
+ JSON.parse(params['posData'])['orderId']
+ rescue JSON::ParserError
+ end
+
+ def status
+ case params['status']
+ when 'complete'
+ 'Completed'
+ when 'confirmed'
+ 'Pending'
+ when 'invalid'
+ 'Failed'
+ end
+ end
+
# When was this payment received by the client.
def received_at
params['invoiceTime'].to_i
@@ -22,32 +38,34 @@ def currency
params['currency']
end
- def amount
- params['price']
+ def gross
+ params['price'].to_f
end
- # the money amount we received in X.2 decimal.
- def btcPrice
- params['btcPrice'].to_f
- end
+ def acknowledge(authcode = nil)
+ uri = URI.parse("#{ActiveMerchant::Billing::Integrations::BitPay.invoicing_url}/#{transaction_id}")
- def status
- params['status'].downcase
- end
+ http = Net::HTTP.new(uri.host, uri.port)
+ http.use_ssl = true
- def acknowledge(authcode = nil)
- authcode == params['posData']
+ request = Net::HTTP::Get.new(uri.path)
+ request.basic_auth @options[:credential1], ''
+
+ response = http.request(request)
+
+ posted_json = JSON.parse(@raw).tap { |j| j.delete('currentTime') }
+ parse(response.body)
+ retrieved_json = JSON.parse(@raw).tap { |j| j.delete('currentTime') }
+
+ posted_json == retrieved_json
+ rescue JSON::ParserError
end
private
-
- # Take the posted data and move the relevant data into a hash
- def parse(post)
- @raw = post.to_s
- for line in @raw.split('&')
- key, value = *line.scan( %r{^([A-Za-z0-9_.]+)\=(.*)$} ).flatten
- params[key] = CGI.unescape(value)
- end
+ def parse(body)
+ @raw = body
+ @params = JSON.parse(@raw)
+ rescue JSON::ParserError
end
end
end
diff --git a/lib/active_merchant/billing/integrations/bit_pay/return.rb b/lib/active_merchant/billing/integrations/bit_pay/return.rb
new file mode 100644
index 00000000000..f7641a80dcb
--- /dev/null
+++ b/lib/active_merchant/billing/integrations/bit_pay/return.rb
@@ -0,0 +1,10 @@
+module ActiveMerchant #:nodoc:
+ module Billing #:nodoc:
+ module Integrations #:nodoc:
+ module BitPay
+ class Return < ActiveMerchant::Billing::Integrations::Return
+ end
+ end
+ end
+ end
+end
diff --git a/lib/active_merchant/billing/integrations/ipay88.rb b/lib/active_merchant/billing/integrations/ipay88.rb
index cc6b77f2c01..b47516428ad 100644
--- a/lib/active_merchant/billing/integrations/ipay88.rb
+++ b/lib/active_merchant/billing/integrations/ipay88.rb
@@ -10,6 +10,10 @@ def self.service_url
"https://www.mobile88.com/epayment/entry.asp"
end
+ def self.requery_url
+ "https://www.mobile88.com/epayment/enquiry.asp"
+ end
+
def self.return(query_string, options={})
Return.new(query_string, options)
end
diff --git a/lib/active_merchant/billing/integrations/ipay88/helper.rb b/lib/active_merchant/billing/integrations/ipay88/helper.rb
index 123f660358b..e742e6194fc 100644
--- a/lib/active_merchant/billing/integrations/ipay88/helper.rb
+++ b/lib/active_merchant/billing/integrations/ipay88/helper.rb
@@ -46,12 +46,16 @@ def initialize(order, account, options = {})
add_field mappings[:signature], signature
end
+ def amount_in_dollars
+ sprintf("%.2f", @amount_in_cents.to_f/100)
+ end
+
def amount=(money)
@amount_in_cents = money.respond_to?(:cents) ? money.cents : money
if money.is_a?(String) or @amount_in_cents.to_i < 0
raise ArgumentError, "money amount must be either a Money object or a positive integer in cents."
end
- add_field mappings[:amount], sprintf("%.2f", @amount_in_cents.to_f/100)
+ add_field mappings[:amount], amount_in_dollars
end
def currency(symbol)
@@ -103,7 +107,7 @@ def sig_components
components = [merchant_key]
components << fields[mappings[:account]]
components << fields[mappings[:order]]
- components << amount_in_cents.to_s.gsub(/[.,]/, '')
+ components << amount_in_dollars.gsub(/[.,]/, '')
components << fields[mappings[:currency]]
components.join
end
diff --git a/lib/active_merchant/billing/integrations/ipay88/notification.rb b/lib/active_merchant/billing/integrations/ipay88/notification.rb
new file mode 100644
index 00000000000..0badfc4b434
--- /dev/null
+++ b/lib/active_merchant/billing/integrations/ipay88/notification.rb
@@ -0,0 +1,103 @@
+module ActiveMerchant #:nodoc:
+ module Billing #:nodoc:
+ module Integrations #:nodoc:
+ module Ipay88
+ class Notification < ActiveMerchant::Billing::Integrations::Notification
+ include ActiveMerchant::PostsData
+
+ def status
+ params["Status"] == '1' ? 'Completed' : 'Failed'
+ end
+
+ def complete?
+ status == 'Completed'
+ end
+
+ def item_id
+ params["RefNo"]
+ end
+
+ def gross
+ params["Amount"]
+ end
+
+ def currency
+ params["Currency"]
+ end
+
+ def account
+ params["MerchantCode"]
+ end
+
+ def payment
+ params["PaymentId"].to_i
+ end
+
+ def remark
+ params["Remark"]
+ end
+
+ def transaction_id
+ params["TransId"]
+ end
+
+ def auth_code
+ params["AuthCode"]
+ end
+
+ def error
+ params["ErrDesc"]
+ end
+
+ def signature
+ params["Signature"]
+ end
+
+ def secure?
+ generated_signature == signature
+ end
+
+ def success?
+ status == 'Completed'
+ end
+
+ def acknowledge
+ secure? && success? && requery == "00"
+ end
+
+ protected
+
+ def generated_signature
+ Helper.sign(sig_components)
+ end
+
+ def sig_components
+ components = [@options[:credential2]]
+ [:account, :payment, :item_id, :amount_in_cents, :currency].each do |i|
+ components << send(i)
+ end
+ components << params["Status"]
+ components.join
+ end
+
+ def requery
+ data = { "MerchantCode" => account, "RefNo" => item_id, "Amount" => gross }
+ params = parameterize(data)
+ ssl_post Ipay88.requery_url, params, { "Content-Length" => params.size.to_s, "User-Agent" => "Active Merchant -- http://activemerchant.org" }
+ end
+
+ private
+
+ def parameterize(params)
+ params.reject { |k, v| v.blank? }.keys.sort.collect { |key| "#{key}=#{CGI.escape(params[key].to_s)}" }.join("&")
+ end
+
+ def amount_in_cents
+ @amount_in_cents ||= (gross || "").gsub(/[.,]/, "")
+ end
+ end
+ end
+ end
+ end
+end
+
diff --git a/lib/active_merchant/billing/integrations/ipay88/return.rb b/lib/active_merchant/billing/integrations/ipay88/return.rb
index 14e1bc8334b..acb9de1f0dc 100644
--- a/lib/active_merchant/billing/integrations/ipay88/return.rb
+++ b/lib/active_merchant/billing/integrations/ipay88/return.rb
@@ -5,88 +5,22 @@ module Billing #:nodoc:
module Integrations #:nodoc:
module Ipay88
class Return < ActiveMerchant::Billing::Integrations::Return
- include ActiveMerchant::PostsData
- def account
- params["MerchantCode"]
- end
-
- def payment
- params["PaymentId"].to_i
- end
-
- def order
- params["RefNo"]
- end
-
- def amount
- params["Amount"]
- end
-
- def currency
- params["Currency"]
- end
-
- def remark
- params["Remark"]
- end
-
- def transaction
- params["TransId"]
- end
-
- def auth_code
- params["AuthCode"]
- end
-
- def status
- params["Status"]
- end
-
- def error
- params["ErrDesc"]
- end
-
- def signature
- params["Signature"]
- end
-
- def secure?
- self.generated_signature == self.signature
+ def initialize(query_string, options = {})
+ super
+ @notification = Notification.new(query_string, options)
end
def success?
- self.secure? && self.requery == "00" && self.status == "1"
- end
-
- protected
-
- def generated_signature
- Helper.sign(self.sig_components)
- end
-
- def sig_components
- components = [@options[:credential2]]
- [:account, :payment, :order, :amount_in_cents, :currency, :status].each do |i|
- components << self.send(i)
- end
- components.join
+ params["Status"] == "1"
end
- def requery
- data = { "MerchantCode" => self.account, "RefNo" => self.order, "Amount" => self.amount }
- params = parameterize(data)
- ssl_post Ipay88.service_url, params, { "Content-Length" => params.size.to_s, "User-Agent" => "Active Merchant -- http://activemerchant.org" }
+ def cancelled?
+ params["ErrDesc"] == 'Customer Cancel Transaction'
end
- private
-
- def parameterize(params)
- params.reject { |k, v| v.blank? }.keys.sort.collect { |key| "#{key}=#{CGI.escape(params[key].to_s)}" }.join("&")
- end
-
- def amount_in_cents
- @amount_in_cents ||= (self.amount || "").gsub(/[.,]/, "")
+ def message
+ params["ErrDesc"]
end
end
end
diff --git a/lib/active_merchant/billing/integrations/notification.rb b/lib/active_merchant/billing/integrations/notification.rb
index 56df8ee8aa1..815916b4c42 100644
--- a/lib/active_merchant/billing/integrations/notification.rb
+++ b/lib/active_merchant/billing/integrations/notification.rb
@@ -61,8 +61,8 @@ def test?
def parse(post)
@raw = post.to_s
for line in @raw.split('&')
- key, value = *line.scan( %r{^([A-Za-z0-9_.]+)\=(.*)$} ).flatten
- params[key] = CGI.unescape(value)
+ key, value = *line.scan( %r{^([A-Za-z0-9_.-]+)\=(.*)$} ).flatten
+ params[key] = CGI.unescape(value.to_s) if key.present?
end
end
end
diff --git a/lib/active_merchant/billing/integrations/pay_fast/notification.rb b/lib/active_merchant/billing/integrations/pay_fast/notification.rb
index 21c402570c1..01bb8bc841b 100644
--- a/lib/active_merchant/billing/integrations/pay_fast/notification.rb
+++ b/lib/active_merchant/billing/integrations/pay_fast/notification.rb
@@ -73,7 +73,7 @@ def gross
params['amount_gross']
end
- # The total in fees which was deducated from the amount.
+ # The total in fees which was deducted from the amount.
def fee
params['amount_fee']
end
diff --git a/lib/active_merchant/billing/integrations/paypal/helper.rb b/lib/active_merchant/billing/integrations/paypal/helper.rb
index c905ae75901..1f894672320 100644
--- a/lib/active_merchant/billing/integrations/paypal/helper.rb
+++ b/lib/active_merchant/billing/integrations/paypal/helper.rb
@@ -69,7 +69,7 @@ def shipping_address(params = {})
if params.has_key?(:phone)
phone = params.delete(:phone).to_s
- # Whipe all non digits
+ # Wipe all non digits
phone.gsub!(/\D+/, '')
if ['US', 'CA'].include?(country_code) && phone =~ /(\d{3})(\d{3})(\d{4})$/
diff --git a/lib/active_merchant/billing/integrations/payu_in.rb b/lib/active_merchant/billing/integrations/payu_in.rb
index 74933f1c7c6..261bc93c9a5 100755
--- a/lib/active_merchant/billing/integrations/payu_in.rb
+++ b/lib/active_merchant/billing/integrations/payu_in.rb
@@ -27,15 +27,8 @@ def self.return(post, options = {})
Return.new(post, options)
end
- def self.checksum(merchant_id, secret_key, *payload_items )
- options = payload_items.pop if Hash === payload_items.last
- options ||= {}
- payload = if options[:reverse] then
- payload_items.dup.push( merchant_id || "" ).unshift( secret_key || "" ).collect{ |x| x.to_s }.join("|")
- else
- payload_items.dup.unshift( merchant_id || "" ).push( secret_key || "" ).collect{ |x| x.to_s }.join("|")
- end
- Digest::SHA512.hexdigest( payload )
+ def self.checksum(merchant_id, secret_key, payload_items )
+ Digest::SHA512.hexdigest([merchant_id, *payload_items, secret_key].join("|"))
end
end
end
diff --git a/lib/active_merchant/billing/integrations/payu_in/helper.rb b/lib/active_merchant/billing/integrations/payu_in/helper.rb
index 32048d309bc..6ac746e9015 100755
--- a/lib/active_merchant/billing/integrations/payu_in/helper.rb
+++ b/lib/active_merchant/billing/integrations/payu_in/helper.rb
@@ -4,10 +4,13 @@ module Integrations #:nodoc:
module PayuIn
class Helper < ActiveMerchant::Billing::Integrations::Helper
+ CHECKSUM_FIELDS = [ 'txnid', 'amount', 'productinfo', 'firstname', 'email', 'udf1', 'udf2', 'udf3', 'udf4',
+ 'udf5', 'udf6', 'udf7', 'udf8', 'udf9', 'udf10']
+
mapping :amount, 'amount'
mapping :account, 'key'
mapping :order, 'txnid'
- mapping :credential2, 'productinfo'
+ mapping :description, 'productinfo'
mapping :customer, :first_name => 'firstname',
:last_name => 'lastname',
@@ -44,26 +47,25 @@ class Helper < ActiveMerchant::Billing::Integrations::Helper
def initialize(order, account, options = {})
super
+ @options = options
self.pg = 'CC'
end
def form_fields
+ sanitize_fields
@fields.merge(mappings[:checksum] => generate_checksum)
end
- def generate_checksum( options = {} )
- checksum_fields = [ :order, :amount, :credential2, { :customer => [ :first_name, :email ] },
- { :user_defined => [ :var1, :var2, :var3, :var4, :var5, :var6, :var7, :var8, :var9, :var10 ] } ]
- checksum_payload_items = checksum_fields.inject( [] ) do | items, field |
- if Hash === field then
- key = field.keys.first
- field[key].inject( items ){ |s,x| items.push( @fields[ mappings[key][x] ] ) }
- else
- items.push( @fields[ mappings[field] ] )
- end
+ def generate_checksum
+ checksum_payload_items = CHECKSUM_FIELDS.map { |field| @fields[field] }
+
+ PayuIn.checksum(@fields["key"], @options[:credential2], checksum_payload_items )
+ end
+
+ def sanitize_fields
+ ['address1', 'address2', 'city', 'state', 'country', 'productinfo', 'email', 'phone'].each do |field|
+ @fields[field].gsub!(/[^a-zA-Z0-9\-_@\/\s.]/, '') if @fields[field]
end
- checksum_payload_items.push( options )
- PayuIn.checksum(@fields["key"], @fields["productinfo"], *checksum_payload_items )
end
end
diff --git a/lib/active_merchant/billing/integrations/payu_in/notification.rb b/lib/active_merchant/billing/integrations/payu_in/notification.rb
index 932c136e7d1..7881a02f9ca 100755
--- a/lib/active_merchant/billing/integrations/payu_in/notification.rb
+++ b/lib/active_merchant/billing/integrations/payu_in/notification.rb
@@ -15,18 +15,10 @@ def complete?
end
def status
- @status ||= if checksum_ok?
- if transaction_id.blank?
- 'Invalid'
- else
- case transaction_status.downcase
- when 'success' then 'Completed'
- when 'failure' then 'Failed'
- when 'pending' then 'Pending'
- end
- end
- else
- 'Tampered'
+ case transaction_status.downcase
+ when 'success' then 'Completed'
+ when 'failure' then 'Failed'
+ when 'pending' then 'Pending'
end
end
@@ -36,7 +28,7 @@ def invoice_ok?( order_id )
# Order amount should be equal to gross - discount
def amount_ok?( order_amount, order_discount = BigDecimal.new( '0.0' ) )
- BigDecimal.new( gross ) == order_amount && BigDecimal.new( discount ) == order_discount
+ BigDecimal.new( gross ) == order_amount && BigDecimal.new( discount.to_s ) == order_discount
end
# Status of transaction return from the PayU. List of possible values:
@@ -129,10 +121,7 @@ def customer_address
end
def user_defined
- return @user_defined if @user_defined
- @user_defined = []
- 10.times{ |i| @user_defined.push( params[ "udf#{i+1}" ] ) }
- @user_defined
+ @user_defined ||= 10.times.map { |i| params["udf#{i + 1}"] }
end
def checksum
@@ -148,9 +137,9 @@ def acknowledge(authcode = nil)
end
def checksum_ok?
- fields = user_defined.dup.push( customer_email, customer_first_name, product_info, gross, invoice, :reverse => true )
- fields.unshift( transaction_status )
- unless PayuIn.checksum(@merchant_id, @secret_key, *fields ) == checksum
+ checksum_fields = [transaction_status, *user_defined.reverse, customer_email, customer_first_name, product_info, gross, invoice]
+
+ unless Digest::SHA512.hexdigest([@secret_key, *checksum_fields, @merchant_id].join("|")) == checksum
@message = 'Return checksum not matching the data provided'
return false
end
diff --git a/lib/active_merchant/billing/integrations/payu_in_paisa/helper.rb b/lib/active_merchant/billing/integrations/payu_in_paisa/helper.rb
index d87c596d1c9..b46561c176e 100644
--- a/lib/active_merchant/billing/integrations/payu_in_paisa/helper.rb
+++ b/lib/active_merchant/billing/integrations/payu_in_paisa/helper.rb
@@ -7,7 +7,7 @@ class Helper < PayuIn::Helper
mapping :service_provider, 'service_provider'
def initialize(order, account, options = {})
- super order, account, options
+ super
self.service_provider = 'payu_paisa'
self.user_defined = { :var2 => order }
end
diff --git a/lib/active_merchant/billing/integrations/payu_in_paisa/notification.rb b/lib/active_merchant/billing/integrations/payu_in_paisa/notification.rb
index df4bfb7eba8..9d930f4df6a 100644
--- a/lib/active_merchant/billing/integrations/payu_in_paisa/notification.rb
+++ b/lib/active_merchant/billing/integrations/payu_in_paisa/notification.rb
@@ -6,16 +6,6 @@ class Notification < PayuIn::Notification
def item_id
params['udf2']
end
-
- def checksum_ok?
- fields = user_defined.reverse.push( customer_email, customer_first_name, product_info, gross, invoice, :reverse => true )
- fields.unshift( transaction_status )
- unless PayuIn.checksum(@merchant_id, @secret_key, *fields ) == checksum
- @message = 'Return checksum not matching the data provided'
- return false
- end
- true
- end
end
end
end
diff --git a/lib/active_merchant/billing/integrations/payu_in_paisa/return.rb b/lib/active_merchant/billing/integrations/payu_in_paisa/return.rb
index b5bfce0af52..8b22eb7b08a 100644
--- a/lib/active_merchant/billing/integrations/payu_in_paisa/return.rb
+++ b/lib/active_merchant/billing/integrations/payu_in_paisa/return.rb
@@ -5,7 +5,7 @@ module PayuInPaisa
class Return < PayuIn::Return
def initialize(query_string, options = {})
- super query_string, options
+ super
@notification = Notification.new(query_string, options)
end
end
diff --git a/lib/active_merchant/billing/integrations/two_checkout/helper.rb b/lib/active_merchant/billing/integrations/two_checkout/helper.rb
index 077b9ae424d..4f4eac351fa 100644
--- a/lib/active_merchant/billing/integrations/two_checkout/helper.rb
+++ b/lib/active_merchant/billing/integrations/two_checkout/helper.rb
@@ -56,7 +56,7 @@ def customer(params = {})
end
# Uses Pass Through Product Parameters to pass in lineitems.
- # (must mark tanigble sales as shipped to settle the transaction)
+ # (must mark tangible sales as shipped to settle the transaction)
def line_item(params = {})
add_field('mode', '2CO')
(max_existing_line_item_id = form_fields.keys.map do |key|
diff --git a/lib/active_merchant/billing/integrations/valitor/helper.rb b/lib/active_merchant/billing/integrations/valitor/helper.rb
index 15630f659de..9a6aeafd214 100644
--- a/lib/active_merchant/billing/integrations/valitor/helper.rb
+++ b/lib/active_merchant/billing/integrations/valitor/helper.rb
@@ -50,7 +50,7 @@ def product(id, options={})
requires!(options, :amount, :description)
options.assert_valid_keys([:description, :quantity, :amount, :discount])
- add_field("Vara_#{id}_Verd", format_amount(options[:amount]))
+ add_field("Vara_#{id}_Verd", format_amount(options[:amount], @fields[mappings[:currency]]))
add_field("Vara_#{id}_Fjoldi", options[:quantity] || "1")
add_field("Vara_#{id}_Lysing", options[:description]) if options[:description]
@@ -76,8 +76,8 @@ def form_fields
@fields.merge('RafraenUndirskrift' => signature)
end
- def format_amount(amount)
- amount.to_f.round
+ def format_amount(amount, currency)
+ Gateway::CURRENCIES_WITHOUT_FRACTIONS.include?(currency) ? amount.to_f.round : sprintf("%.2f", amount)
end
end
end
diff --git a/lib/active_merchant/billing/integrations/valitor/response_fields.rb b/lib/active_merchant/billing/integrations/valitor/response_fields.rb
index 636a0cc7081..29c8176a0a3 100644
--- a/lib/active_merchant/billing/integrations/valitor/response_fields.rb
+++ b/lib/active_merchant/billing/integrations/valitor/response_fields.rb
@@ -36,7 +36,7 @@ def received_at
end
def gross
- "%0.2f" % params['Upphaed'].to_s
+ "%0.2f" % params['Upphaed'].to_s.sub(',', '.')
end
def card_type
@@ -94,4 +94,4 @@ def acknowledge(authcode = nil)
end
end
end
-end
\ No newline at end of file
+end
diff --git a/lib/active_merchant/billing/integrations/verkkomaksut/notification.rb b/lib/active_merchant/billing/integrations/verkkomaksut/notification.rb
index aaaf5eee163..53ce8eaac3c 100644
--- a/lib/active_merchant/billing/integrations/verkkomaksut/notification.rb
+++ b/lib/active_merchant/billing/integrations/verkkomaksut/notification.rb
@@ -40,7 +40,7 @@ def status
end
end
- # Acknowldges the payment. If the authcodes match, returns true.
+ # Acknowledges the payment. If the authcodes match, returns true.
def acknowledge(authcode = nil)
return_authcode = [params["ORDER_NUMBER"], params["TIMESTAMP"], params["PAID"], params["METHOD"], authcode].join("|")
Digest::MD5.hexdigest(return_authcode).upcase == params["RETURN_AUTHCODE"]
diff --git a/lib/active_merchant/billing/integrations/wirecard_checkout_page.rb b/lib/active_merchant/billing/integrations/wirecard_checkout_page.rb
new file mode 100644
index 00000000000..c305a20f78f
--- /dev/null
+++ b/lib/active_merchant/billing/integrations/wirecard_checkout_page.rb
@@ -0,0 +1,39 @@
+=begin
+ * Shop System Plugins - Terms of use
+ *
+ * This terms of use regulates warranty and liability between Wirecard Central Eastern Europe (subsequently referred to as WDCEE) and it's
+ * contractual partners (subsequently referred to as customer or customers) which are related to the use of plugins provided by WDCEE.
+ *
+ * The Plugin is provided by WDCEE free of charge for it's customers and must be used for the purpose of WDCEE's payment platform
+ * integration only. It explicitly is not part of the general contract between WDCEE and it's customer. The plugin has successfully been tested
+ * under specific circumstances which are defined as the shopsystem's standard configuration (vendor's delivery state). The Customer is
+ * responsible for testing the plugin's functionality before putting it into production environment.
+ * The customer uses the plugin at own risk. WDCEE does not guarantee it's full functionality neither does WDCEE assume liability for any
+ * disadvantage related to the use of this plugin. By installing the plugin into the shopsystem the customer agrees to the terms of use.
+ * Please do not use this plugin if you do not agree to the terms of use!
+=end
+
+module ActiveMerchant #:nodoc:
+ module Billing #:nodoc:
+ module Integrations #:nodoc:
+ module WirecardCheckoutPage
+ autoload :Common, File.dirname(__FILE__) + '/wirecard_checkout_page/common.rb'
+ autoload :Helper, File.dirname(__FILE__) + '/wirecard_checkout_page/helper.rb'
+ autoload :Notification, File.dirname(__FILE__) + '/wirecard_checkout_page/notification.rb'
+ autoload :Return, File.dirname(__FILE__) + '/wirecard_checkout_page/return.rb'
+
+ mattr_accessor :service_url
+ self.service_url = 'https://checkout.wirecard.com/page/init.php'
+
+ def self.notification(post, options)
+ Notification.new(post, options)
+ end
+
+ def self.return(postdata, options)
+ Return.new(postdata, options)
+ end
+
+ end
+ end
+ end
+end
diff --git a/lib/active_merchant/billing/integrations/wirecard_checkout_page/common.rb b/lib/active_merchant/billing/integrations/wirecard_checkout_page/common.rb
new file mode 100644
index 00000000000..88013a39e5b
--- /dev/null
+++ b/lib/active_merchant/billing/integrations/wirecard_checkout_page/common.rb
@@ -0,0 +1,104 @@
+=begin
+ * Shop System Plugins - Terms of use
+ *
+ * This terms of use regulates warranty and liability between Wirecard Central Eastern Europe (subsequently referred to as WDCEE) and it's
+ * contractual partners (subsequently referred to as customer or customers) which are related to the use of plugins provided by WDCEE.
+ *
+ * The Plugin is provided by WDCEE free of charge for it's customers and must be used for the purpose of WDCEE's payment platform
+ * integration only. It explicitly is not part of the general contract between WDCEE and it's customer. The plugin has successfully been tested
+ * under specific circumstances which are defined as the shopsystem's standard configuration (vendor's delivery state). The Customer is
+ * responsible for testing the plugin's functionality before putting it into production enviroment.
+ * The customer uses the plugin at own risk. WDCEE does not guarantee it's full functionality neither does WDCEE assume liability for any
+ * disadvantage related to the use of this plugin. By installing the plugin into the shopsystem the customer agrees to the terms of use.
+ * Please do not use this plugin if you do not agree to the terms of use!
+=end
+
+module ActiveMerchant #:nodoc:
+ module Billing #:nodoc:
+ module Integrations #:nodoc:
+ module WirecardCheckoutPage
+ module Common
+
+ mattr_accessor :paymenttypes
+ self.paymenttypes = %w(
+ SELECT
+ CCARD
+ BANCONTACT_MISTERCASH
+ C2P
+ CCARD-MOTO
+ EKONTO
+ ELV
+ EPS
+ GIROPAY
+ IDL
+ INSTALLMENT
+ INSTANTBANK
+ INVOICE
+ MAESTRO
+ MONETA
+ MPASS
+ PRZELEWY24
+ PAYPAL
+ PBX
+ POLI
+ PSC
+ QUICK
+ SKRILLDIRECT
+ SKRILLWALLET
+ SOFORTUEBERWEISUNG)
+
+ def message
+ @message
+ end
+
+ def verify_response(params, secret)
+
+ logstr = ''
+ params.each { |key, value|
+ logstr += "#{key} #{value}\n"
+ }
+
+ @paymentstate = 'FAILURE'
+
+ unless params.has_key?('paymentState')
+ @message = "paymentState is missing"
+ return false
+ end
+
+ if params['paymentState'] == 'SUCCESS' || params['paymentState'] == 'PENDING'
+ unless params.has_key?('responseFingerprint')
+ @message = "responseFingerprint is missing"
+ return false
+ end
+
+ unless params.has_key?('responseFingerprintOrder')
+ @message = "responseFingerprintOrder is missing"
+ return false
+ end
+
+ end
+
+ if params['paymentState'] == 'SUCCESS' || params['paymentState'] == 'PENDING'
+ fields = params['responseFingerprintOrder'].split(",")
+ values = ''
+ fields.each { |f|
+ values += f == 'secret' ? secret : params[f]
+ }
+
+
+ if Digest::MD5.hexdigest(values) != params['responseFingerprint']
+ @message = "responseFingerprint verification failed"
+ return false
+ end
+ end
+
+ @paymentstate = params['paymentState']
+ true
+ end
+
+ end
+
+ end
+ end
+ end
+end
diff --git a/lib/active_merchant/billing/integrations/wirecard_checkout_page/helper.rb b/lib/active_merchant/billing/integrations/wirecard_checkout_page/helper.rb
new file mode 100644
index 00000000000..62ec0db4d15
--- /dev/null
+++ b/lib/active_merchant/billing/integrations/wirecard_checkout_page/helper.rb
@@ -0,0 +1,145 @@
+module ActiveMerchant #:nodoc:
+ module Billing #:nodoc:
+ module Integrations #:nodoc:
+ module WirecardCheckoutPage
+ class Helper < ActiveMerchant::Billing::Integrations::Helper
+ include Common
+
+ PLUGIN_NAME = 'ActiveMerchant_WirecardCheckoutPage'
+ PLUGIN_VERSION = '1.0.0'
+
+ # Replace with the real mapping
+ mapping :account, 'customerId'
+ mapping :amount, 'amount'
+
+ mapping :order, 'xActiveMerchantOrderId'
+
+ mapping :customer, :first_name => 'consumerBillingFirstName',
+ :last_name => 'consumerBillingLastName',
+ :email => 'consumerEmail',
+ :phone => 'consumerBillingPhone',
+ :ipaddress => 'consumerIpAddress',
+ :user_agent => 'consumerUserAgent',
+ :fax => 'consumerBillingFax',
+ :birthdate => 'consumerBirthDate' # mandatory for INVOICE and INSTALLMENT
+
+ mapping :billing_address, :city => 'consumerBillingCity',
+ :address1 => 'consumerBillingAddress1',
+ :address2 => 'consumerBillingAddress2',
+ :state => 'consumerBillingState',
+ :zip => 'consumerBillingZipCode',
+ :country => 'consumerBillingCountry'
+
+ mapping :shipping_address, :first_name => 'consumerShippingFirstName',
+ :last_name => 'consumerShippingLastName',
+ :address1 => 'consumerShippingAddress1',
+ :address2 => 'consumerShippingAddress2',
+ :city => 'consumerShippingCity',
+ :state => 'consumerShippingState',
+ :country => 'consumerShippingCountry',
+ :zip => 'consumerShippingZipCode',
+ :phone => 'consumerShippingPhone',
+ :fax => 'consumerShippingFax'
+
+ mapping :currency, 'currency'
+ mapping :language, 'language' # language for displayed texts on payment page
+
+ mapping :description, 'orderDescription' # unique description of the consumer's order in a human readable form
+
+ mapping :shop_service_url, 'serviceUrl' # URL of your service page containing contact information
+
+ mapping :notify_url, 'confirmUrl'
+ mapping :return_url, 'successUrl'
+
+ # defaulting to return_url
+ mapping :cancel_return_url, 'cancelUrl'
+ mapping :pending_url, 'pendingUrl'
+ mapping :failure_url, 'failureUrl'
+
+ # optional parameters
+ mapping :window_name, 'windowName' # window.name of browser window where payment page is opened
+ mapping :duplicate_request_check, 'duplicateRequestCheck' # check for duplicate requests done by your consumer
+ mapping :customer_statement, 'customerStatement' # text displayed on invoice of financial institution of your consumer
+ mapping :order_reference, 'orderReference' # unique order reference id sent from merchant to financial institution
+ mapping :display_text, 'displayText' # text displayed to your consumer within the payment page
+ mapping :image_url, 'imageUrl' # URL of your web shop where your web shop logo is located
+ mapping :max_retries, 'maxRetries' # maximum number of attempted payments for the same order
+ mapping :auto_deposit, 'autoDeposit' # enable automated debiting of payments
+ mapping :financial_institution, 'financialInstitution' # based on pre-selected payment type a sub-selection of financial institutions regarding to pre-selected payment type
+
+ # not used
+ mapping :tax, ''
+ mapping :shipping, ''
+
+ def initialize(order, customer_id, options = {})
+ @paymenttype = options.delete(:paymenttype)
+
+ raise "Unknown Paymenttype: " + @paymenttype if paymenttypes.find_index(@paymenttype) == nil
+
+ @secret = options.delete(:secret)
+ @customer_id = customer_id
+ @shop_id = options.delete(:shop_id)
+ super
+ end
+
+ def add_version(shop_name, shop_version)
+ add_field('pluginVersion', Base64.encode64(shop_name + ';' + shop_version + ';ActiveMerchant;' + PLUGIN_NAME + ';' + PLUGIN_VERSION))
+ end
+
+ def add_standard_fields
+ addfields = {}
+ addfields['shopId'] = @shop_id if !@shop_id.blank?
+ addfields['paymentType'] = @paymenttype
+
+ addfields[mappings[:pending_url]] = @fields[mappings[:return_url]] unless @fields.has_key?(mappings[:pending_url])
+ addfields[mappings[:cancel_return_url]] = @fields[mappings[:return_url]] unless @fields.has_key?(mappings[:cancel_return_url])
+ addfields[mappings[:failure_url]] = @fields[mappings[:return_url]] unless @fields.has_key?(mappings[:failure_url])
+
+ addfields
+ end
+
+ def add_request_fingerprint(fpfields)
+ addfields = {}
+ fingerprint_order = %w(secret)
+ fingerprint_values = @secret.to_s
+ fpfields.each { |key, value|
+ next if key == 'pluginVersion'
+ fingerprint_order.append key
+ fingerprint_values += value.to_s
+ }
+
+ fingerprint_order.append 'requestFingerprintOrder'
+ fingerprint_values += fingerprint_order.join(',')
+
+ addfields['requestFingerprintOrder'] = fingerprint_order.join(',')
+ addfields['requestFingerprint'] = Digest::MD5.hexdigest(fingerprint_values)
+
+ return addfields
+ end
+
+ def form_fields
+ result = {}
+ result.merge!(@fields)
+ result.merge!(add_standard_fields)
+ result.merge!(add_request_fingerprint(result))
+ result
+ end
+
+ def secret
+ @secret
+ end
+
+ def customer_id
+ @customer_id
+ end
+
+ def shop_id
+ @shop_id
+ end
+
+ end
+
+ end
+ end
+ end
+end
\ No newline at end of file
diff --git a/lib/active_merchant/billing/integrations/wirecard_checkout_page/notification.rb b/lib/active_merchant/billing/integrations/wirecard_checkout_page/notification.rb
new file mode 100644
index 00000000000..73590b84c92
--- /dev/null
+++ b/lib/active_merchant/billing/integrations/wirecard_checkout_page/notification.rb
@@ -0,0 +1,101 @@
+require 'net/http'
+
+module ActiveMerchant #:nodoc:
+ module Billing #:nodoc:
+ module Integrations #:nodoc:
+ module WirecardCheckoutPage
+ class Notification < ActiveMerchant::Billing::Integrations::Notification
+ include Common
+
+ def complete?
+ @paymentstate == 'SUCCESS'
+ end
+
+ def item_id
+ params['xActiveMerchantOrderId']
+ end
+
+ def transaction_id
+ params['orderNumber']
+ end
+
+ # When was this payment received by the client.
+ def received_at
+ nil
+ end
+
+ # the money amount we received in X.2 decimal.
+ def gross
+ params['amount']
+ end
+
+ # Was this a test transaction?
+ def test?
+ false
+ end
+
+ def status
+ case @paymentstate
+ when 'SUCCESS'
+ 'Completed'
+ when 'PENDING'
+ 'Pending'
+ when 'CANCEL'
+ 'Cancelled'
+ when 'FAILURE'
+ 'Failed'
+ else
+ 'Error'
+ end
+ end
+
+ def status_code
+ @paymentstate
+ end
+
+
+ # Acknowledge the transaction to WirecardCheckoutPage. This method has to be called after a new
+ # apc arrives. WirecardCheckoutPage will verify that all the information we received are correct and will return a
+ # ok or a fail.
+ #
+ # Example:
+ #
+ # def ipn
+ # notify = WirecardCheckoutPageNotification.new(request.raw_post, options)
+ #
+ # if notify.acknowledge
+ # ... process order ... if notify.complete?
+ # else
+ # ... log possible hacking attempt ...
+ # end
+ def acknowledge
+ verify_response(params, @options[:secret])
+ end
+
+ def response(umessage = nil)
+ if @message || umessage
+ ''
+ else
+ ''
+ end
+ end
+
+ def method_missing(method_id, *args)
+ return params[method_id.to_s] if params.has_key?(method_id.to_s)
+ end
+
+ private
+
+ # Take the posted data and move the relevant data into a hash
+ def parse(post)
+ @raw = post.to_s
+ for line in @raw.split('&')
+ key, value = *line.scan( %r{^([A-Za-z0-9_.]+)\=(.*)$} ).flatten
+ params[key] = CGI.unescape(value)
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/active_merchant/billing/integrations/wirecard_checkout_page/return.rb b/lib/active_merchant/billing/integrations/wirecard_checkout_page/return.rb
new file mode 100644
index 00000000000..0e3944a67a5
--- /dev/null
+++ b/lib/active_merchant/billing/integrations/wirecard_checkout_page/return.rb
@@ -0,0 +1,35 @@
+module ActiveMerchant #:nodoc:
+ module Billing #:nodoc:
+ module Integrations #:nodoc:
+ module WirecardCheckoutPage
+ class Return < ActiveMerchant::Billing::Integrations::Return
+ include Common
+
+ def initialize(postdata, options = {})
+ @params = parse(postdata)
+ @options = options
+ verify_response(@params, options[:secret])
+ end
+
+ def success?
+ @paymentstate == 'SUCCESS'
+ end
+
+ def cancelled?
+ @paymentstate == 'CANCEL'
+ end
+
+ def pending?
+ @paymentstate == 'PENDING'
+ end
+
+ def method_missing(method_id, *args)
+ return params[method_id.to_s] if params.has_key?(method_id.to_s)
+ end
+
+ end
+ end
+ end
+ end
+end
+
diff --git a/lib/active_merchant/billing/integrations/world_pay/helper.rb b/lib/active_merchant/billing/integrations/world_pay/helper.rb
index 68ab9d911dd..cd80897cd80 100644
--- a/lib/active_merchant/billing/integrations/world_pay/helper.rb
+++ b/lib/active_merchant/billing/integrations/world_pay/helper.rb
@@ -58,7 +58,7 @@ def customer(params={})
end
# Support for a MD5 hash of selected fields to prevent tampering
- # For futher information read the tech note at the address below:
+ # For further information read the tech note at the address below:
# http://support.worldpay.com/kb/integration_guides/junior/integration/help/tech_notes/sjig_tn_009.html
def encrypt(secret, fields = [:amount, :currency, :account, :order])
signature_fields = fields.collect{ |field| mappings[field] }
@@ -98,4 +98,4 @@ def combined_params(params={})
end
end
end
-end
\ No newline at end of file
+end
diff --git a/lib/active_merchant/version.rb b/lib/active_merchant/version.rb
index 5a00f3ccb4b..69eda89b8a7 100644
--- a/lib/active_merchant/version.rb
+++ b/lib/active_merchant/version.rb
@@ -1,3 +1,3 @@
module ActiveMerchant
- VERSION = "1.39.2"
+ VERSION = "1.42.2"
end
diff --git a/test/fixtures.yml b/test/fixtures.yml
index 377ee656e79..598e9269d79 100644
--- a/test/fixtures.yml
+++ b/test/fixtures.yml
@@ -10,6 +10,11 @@
#
# Paste any required PEM certificates after the pem key.
#
+
+app55:
+ api_key: "QDtACYMCFqtuKOQ22QtCkGR1TzD7XM8i"
+ api_secret: "yT1FRpuusBIQoEBIfIQ8bPStkl7yzdTz"
+
authorize_net:
login: X
password: Y
@@ -59,6 +64,7 @@ braintree_blue:
merchant_id: X
public_key: Y
private_key: Z
+ merchant_account_id: A
braintree_blue_with_processing_rules:
merchant_id: X
@@ -85,6 +91,9 @@ cyber_source:
login: X
password: Y
+conekta:
+ key: 1tv5yJp3xnVZ7eK67m4h
+
data_cash:
login: X
password: Y
@@ -119,10 +128,9 @@ eway_managed:
username: 'test@eway.com.au'
password: 'test123'
-# Working credentials, no need to replace
eway_rapid:
- login: "F9802CIVgUgNaD8y/H52MBMnL5OvMoy4cYimpi1L/dCXeNNR6or3vLPoC9GjeLVdA7ymi+"
- password: "sandbox1"
+ login: LOGIN
+ password: PASSWORD
# Working credentials, no need to replace
exact:
@@ -328,6 +336,11 @@ pay_gate_xml:
login: '10011021600'
password: 'test'
+payex:
+ account: ACCOUNT
+ # encryption key is generated via the PayEx Admin console
+ encryption_key: ENCRYPTION_KEY
+
payflow:
login: LOGIN
password: PASSWORD
@@ -364,6 +377,10 @@ paypal_signature:
password: PASSWORD
signature: SIGNATURE
+payu_in:
+ login: C0Dr8m
+ secret: 3sf0jURk
+
payway:
username:
password:
@@ -456,6 +473,10 @@ psl_visa_debit_address:
state:
zip:
+payscout:
+ username: demo
+ password: password
+
# Quickpay offers a test account.
# To log in to the manager, use demo@quickpay.net and test234
quickpay:
@@ -473,6 +494,11 @@ quantum:
login: X
password: Y
+raven_pac_net:
+ user: ernest
+ secret: "all good men die young"
+ prn: 840033
+
realex:
login: X
password: Y
@@ -578,6 +604,10 @@ skipjack:
login: X
password: Y
+so_easy_pay:
+ login: 110159
+ password: b1fe9de37c234ef8fd53668377076687d6314dc8f6146023338d61b5969719e0
+
# Working credentials, no need to replace
spreedly_core:
login: "4Y9bVkOCpYesPQOfDi7TXQyUw50"
@@ -588,6 +618,12 @@ stripe:
login:
fee_refund_login:
+# Working credentials, no need to replace
+swipe_checkout:
+ login: 2077103073D8B5
+ api_key: f2fe4efd5033edfaed9e4aad319ef4d34536a10eea07f90f182616d7216ae2b8
+ region: NZ
+
trans_first:
login: LOGIN
password: PASSWORD
@@ -651,3 +687,8 @@ iats_payments:
bit_pay:
api_key: 'rKrahSl7WRrYeKRUhGzbvW3nBzo0jG4FPaL8uPYaoPk'
+
+wirecard_checkout_page:
+ secret: B8AKTPWBRMNBV455FG6M2DANE99WU2
+ shop_id: ''
+ paymenttype: IDL
diff --git a/test/remote/gateways/remote_app55_test.rb b/test/remote/gateways/remote_app55_test.rb
new file mode 100644
index 00000000000..b52a889f878
--- /dev/null
+++ b/test/remote/gateways/remote_app55_test.rb
@@ -0,0 +1,65 @@
+require 'test_helper'
+
+class RemoteApp55Test < Test::Unit::TestCase
+ def setup
+ @gateway = App55Gateway.new(fixtures(:app55))
+
+ @amount = 100
+ @credit_card = credit_card('4111111111111111')
+ @duff_card = credit_card('400030001111222')
+ @customer = generate_unique_id
+
+ @options = {
+ billing_address: address,
+ description: 'app55 active merchant remote test',
+ currency: "GBP"
+ }
+ end
+
+ def test_successful_purchase
+ assert response = @gateway.purchase(@amount, @credit_card, @options)
+ assert_success response
+ assert_not_nil response.params["sig"]
+ assert_not_nil response.params["transaction"]["auth_code"]
+ assert_not_nil response.params["transaction"]["id"]
+ assert_equal response.params["transaction"]["id"], response.authorization
+ assert_equal @options[:description], response.params["transaction"]["description"]
+ assert_equal @options[:currency], response.params["transaction"]["currency"]
+ assert_equal "%.2f" % (@amount / 100), response.params["transaction"]["amount"]
+ end
+
+ def test_unsuccessful_purchase
+ assert response = @gateway.purchase(@amount, @duff_card, @options)
+ assert_failure response
+ assert_equal "Invalid card number supplied.", response.message
+ end
+
+ def test_authorize_and_capture
+ amount = @amount
+ assert response = @gateway.authorize(amount, @credit_card, @options)
+ assert_success response
+ assert response.params["transaction"]
+ assert_equal @options[:description], response.params["transaction"]["description"]
+ assert_equal @options[:currency], response.params["transaction"]["currency"]
+ assert_equal "%.2f" % (@amount / 100), response.params["transaction"]["amount"]
+
+ assert capture = @gateway.capture(amount, response.authorization)
+ assert_success capture
+ end
+
+ def test_failed_capture
+ assert response = @gateway.capture(@amount, '')
+ assert_failure response
+ assert !response.params["transaction"]
+ end
+
+ def test_invalid_login
+ gateway = App55Gateway.new(
+ api_key: 'xNSACPYP9ZDUr4860gV9vqvR7TxmVMJP',
+ api_secret: 'bogus'
+ )
+ assert response = gateway.purchase(@amount, @credit_card, @options)
+ assert_failure response
+ assert_equal 'The supplied API Secret does not appear to be valid.', response.message
+ end
+end
diff --git a/test/remote/gateways/remote_balanced_test.rb b/test/remote/gateways/remote_balanced_test.rb
index 1ea8135dcf3..61a4cf135a8 100644
--- a/test/remote/gateways/remote_balanced_test.rb
+++ b/test/remote/gateways/remote_balanced_test.rb
@@ -42,6 +42,14 @@ def test_unsuccessful_purchase
assert_match /Account Frozen/, response.message
end
+ def test_passing_appears_on_statement
+ options = @options.merge(appears_on_statement_as: "Homer Electric")
+ assert response = @gateway.purchase(@amount, @credit_card, options)
+
+ assert_success response
+ assert_equal "Homer Electric", response.params['appears_on_statement_as']
+ end
+
def test_authorize_and_capture
amount = @amount
assert auth = @gateway.authorize(amount, @credit_card, @options)
diff --git a/test/remote/gateways/remote_braintree_blue_test.rb b/test/remote/gateways/remote_braintree_blue_test.rb
index 5929b5d5d21..ed5b90cc0eb 100644
--- a/test/remote/gateways/remote_braintree_blue_test.rb
+++ b/test/remote/gateways/remote_braintree_blue_test.rb
@@ -51,19 +51,12 @@ def test_successful_authorize_with_order_id
assert_equal '123', response.params["braintree_transaction"]["order_id"]
end
- def test_successful_authorize_with_merchant_account_id
- assert response = @gateway.authorize(@amount, @credit_card, :merchant_account_id => 'sandbox_credit_card_non_default')
- assert_success response
- assert_equal '1000 Approved', response.message
- assert_equal 'sandbox_credit_card_non_default', response.params["braintree_transaction"]["merchant_account_id"]
- end
-
def test_successful_purchase_using_vault_id
assert response = @gateway.store(@credit_card)
assert_success response
assert_equal 'OK', response.message
customer_vault_id = response.params["customer_vault_id"]
- assert_match(/\A\d{6,7}\z/, customer_vault_id)
+ assert_match(/\A\d+\z/, customer_vault_id)
assert response = @gateway.purchase(@amount, customer_vault_id)
assert_success response
@@ -77,7 +70,7 @@ def test_successful_purchase_using_vault_id_as_integer
assert_success response
assert_equal 'OK', response.message
customer_vault_id = response.params["customer_vault_id"]
- assert_match /\A\d{6,7}\z/, customer_vault_id
+ assert_match /\A\d+\z/, customer_vault_id
assert response = @gateway.purchase(@amount, customer_vault_id.to_i)
assert_success response
@@ -93,13 +86,6 @@ def test_successful_validate_on_store
assert_equal 'OK', response.message
end
- def test_successful_validate_on_store_with_verification_merchant_account
- card = credit_card('4111111111111111', :verification_value => '101')
- assert response = @gateway.store(card, :verify_card => true, :verification_merchant_account_id => 'sandbox_credit_card_non_default')
- assert_success response
- assert_equal 'OK', response.message
- end
-
def test_failed_validate_on_store
card = credit_card('4000111111111115', :verification_value => '200')
assert response = @gateway.store(card, :verify_card => true)
@@ -148,6 +134,40 @@ def test_successful_store_with_billing_address
assert_equal purchase_response.params['braintree_transaction']['billing_details'], response_billing_details
end
+ def test_successful_store_with_credit_card_token
+ credit_card = credit_card('5105105105105100')
+ credit_card_token = generate_unique_id
+ assert response = @gateway.store(credit_card, credit_card_token: credit_card_token)
+ assert_success response
+ assert_equal 'OK', response.message
+ assert_equal credit_card_token, response.params["braintree_customer"]["credit_cards"][0]["token"]
+ end
+
+ def test_successful_store_with_new_customer_id
+ credit_card = credit_card('5105105105105100')
+ customer_id = generate_unique_id
+ assert response = @gateway.store(credit_card, customer: customer_id)
+ assert_success response
+ assert_equal 'OK', response.message
+ assert_equal customer_id, response.authorization
+ assert_equal customer_id, response.params["braintree_customer"]["id"]
+ end
+
+ def test_successful_store_with_existing_customer_id
+ credit_card = credit_card('5105105105105100')
+ customer_id = generate_unique_id
+ assert response = @gateway.store(credit_card, customer: customer_id)
+ assert_success response
+ assert_equal 1, @braintree_backend.customer.find(customer_id).credit_cards.size
+
+ assert response = @gateway.store(credit_card, customer: customer_id)
+ assert_success response
+ assert_equal 2, @braintree_backend.customer.find(customer_id).credit_cards.size
+ assert_equal customer_id, response.params["customer_vault_id"]
+ assert_equal customer_id, response.authorization
+ assert_not_nil response.params["credit_card_token"]
+ end
+
def test_successful_purchase
assert response = @gateway.purchase(@amount, @credit_card, @options)
assert_success response
@@ -184,7 +204,7 @@ def test_transaction_fails_with_bad_avs_with_avs_rules
)
)
- assert_failure response
+ assert_failure response, "This test will fail unless you specify a braintree_blue_with_processing_rules that has AVS required."
assert_equal("Transaction declined - gateway rejected", response.message)
assert_equal({'code' => nil, 'message' => nil, 'street_match' => 'N', 'postal_match' => 'N'}, response.avs_result)
end
@@ -205,7 +225,8 @@ def test_transaction_fails_with_bad_cvv_with_cvv_rules
gateway = BraintreeGateway.new(fixtures(:braintree_blue_with_processing_rules))
assert response = gateway.purchase(@amount, credit_card('5105105105105100', :verification_value => '200'))
- assert_failure response
+ assert_failure response, "This test will fail unless you specify a braintree_blue_with_processing_rules that has CVV required."
+
assert_equal("Transaction declined - gateway rejected", response.message)
assert_equal({'code' => 'N', 'message' => ''}, response.cvv_result)
end
@@ -225,7 +246,7 @@ def test_purchase_with_store_using_random_customer_id
)
assert_success response
assert_equal '1000 Approved', response.message
- assert_match(/\A\d{6,7}\z/, response.params["customer_vault_id"])
+ assert_match(/\A\d+\z/, response.params["customer_vault_id"])
assert_equal '510510', response.params["braintree_transaction"]["vault_customer"]["credit_cards"][0]["bin"]
assert_equal '510510', @braintree_backend.customer.find(response.params["customer_vault_id"]).credit_cards[0].bin
end
@@ -290,11 +311,9 @@ def test_unsuccessful_purchase_declined
end
def test_unsuccessful_purchase_validation_error
- assert response = @gateway.purchase(@amount, @credit_card,
- @options.merge(:email => "invalid_email")
- )
+ assert response = @gateway.purchase(@amount, credit_card('51051051051051000'))
assert_failure response
- assert_equal 'Email is an invalid format. (81604)', response.message
+ assert_match %r{Credit card number is invalid\. \(81715\)}, response.message
assert_equal nil, response.params["braintree_transaction"]
end
@@ -351,7 +370,7 @@ def test_successful_add_to_vault_with_store_method
assert response = @gateway.store(@credit_card)
assert_success response
assert_equal 'OK', response.message
- assert_match(/\A\d{6,7}\z/, response.params["customer_vault_id"])
+ assert_match(/\A\d+\z/, response.params["customer_vault_id"])
end
def test_failed_add_to_vault
@@ -362,7 +381,7 @@ def test_failed_add_to_vault
assert_equal nil, response.params["customer_vault_id"]
end
- def test_unstore
+ def test_unstore_customer
assert response = @gateway.store(@credit_card)
assert_success response
assert_equal 'OK', response.message
@@ -371,33 +390,22 @@ def test_unstore
assert_success delete_response
end
- def test_unstore_with_delete_method
+ def test_unstore_credit_card
assert response = @gateway.store(@credit_card)
assert_success response
assert_equal 'OK', response.message
- assert customer_vault_id = response.params["customer_vault_id"]
- assert delete_response = @gateway.delete(customer_vault_id)
+ assert credit_card_token = response.params["credit_card_token"]
+ assert delete_response = @gateway.unstore(nil, credit_card_token: credit_card_token)
assert_success delete_response
end
- def test_successful_credit
- assert response = @gateway.credit(@amount, @credit_card, @options)
- assert_success response
- assert_equal '1002 Processed', response.message
- assert_equal 'submitted_for_settlement', response.params["braintree_transaction"]["status"]
- end
-
- def test_successful_credit_with_merchant_account_id
- assert response = @gateway.credit(@amount, @credit_card, :merchant_account_id => 'sandbox_credit_card_non_default')
+ def test_unstore_with_delete_method
+ assert response = @gateway.store(@credit_card)
assert_success response
- assert_equal '1002 Processed', response.message
- assert_equal 'submitted_for_settlement', response.params["braintree_transaction"]["status"]
- end
-
- def test_failed_credit
- assert response = @gateway.credit(@amount, credit_card('5105105105105101'), @options)
- assert_failure response
- assert_equal 'Credit card number is invalid. (81715)', response.message
+ assert_equal 'OK', response.message
+ assert customer_vault_id = response.params["customer_vault_id"]
+ assert delete_response = @gateway.delete(customer_vault_id)
+ assert_success delete_response
end
def test_successful_update
@@ -411,7 +419,7 @@ def test_successful_update
assert_success response
assert_equal 'OK', response.message
customer_vault_id = response.params["customer_vault_id"]
- assert_match(/\A\d{6,7}\z/, customer_vault_id)
+ assert_match(/\A\d+\z/, customer_vault_id)
assert_equal "old@example.com", response.params["braintree_customer"]["email"]
assert_equal "Old First", response.params["braintree_customer"]["first_name"]
assert_equal "Old Last", response.params["braintree_customer"]["last_name"]
@@ -446,11 +454,10 @@ def test_failed_customer_update
assert response = @gateway.update(
customer_vault_id,
- credit_card('5105105105105100'),
- :email => "invalid-email"
+ credit_card('51051051051051001')
)
assert_failure response
- assert_equal 'Email is an invalid format. (81604)', response.message
+ assert_equal 'Credit card number is invalid. (81715)', response.message
assert_equal nil, response.params["braintree_customer"]
assert_equal nil, response.params["customer_vault_id"]
end
@@ -491,9 +498,43 @@ def test_failed_credit_card_update_on_verify
end
def test_customer_does_not_have_credit_card_failed_update
- customer_without_credit_card = @braintree_backend.create
- assert response = @gateway.update(customer_without_credit_card.id, credit_card('5105105105105100'))
+ customer_without_credit_card = @braintree_backend.customer.create
+ assert response = @gateway.update(customer_without_credit_card.customer.id, credit_card('5105105105105100'))
assert_failure response
assert_equal 'Braintree::NotFoundError', response.message
end
+
+ def test_successful_credit
+ assert response = @gateway.credit(@amount, @credit_card, @options)
+ assert_success response, "You must get credits enabled in your Sandbox account for this to pass."
+ assert_equal '1002 Processed', response.message
+ assert_equal 'submitted_for_settlement', response.params["braintree_transaction"]["status"]
+ end
+
+ def test_failed_credit
+ assert response = @gateway.credit(@amount, credit_card('5105105105105101'), @options)
+ assert_failure response
+ assert_equal 'Credit card number is invalid. (81715)', response.message, "You must get credits enabled in your Sandbox account for this to pass"
+ end
+
+ def test_successful_credit_with_merchant_account_id
+ assert response = @gateway.credit(@amount, @credit_card, :merchant_account_id => fixtures(:braintree_blue)[:merchant_account_id])
+ assert_success response, "You must specify a valid :merchant_account_id key in your fixtures.yml AND get credits enabled in your Sandbox account for this to pass."
+ assert_equal '1002 Processed', response.message
+ assert_equal 'submitted_for_settlement', response.params["braintree_transaction"]["status"]
+ end
+
+ def test_successful_authorize_with_merchant_account_id
+ assert response = @gateway.authorize(@amount, @credit_card, :merchant_account_id => fixtures(:braintree_blue)[:merchant_account_id])
+ assert_success response, "You must specify a valid :merchant_account_id key in your fixtures.yml for this to pass."
+ assert_equal '1000 Approved', response.message
+ assert_equal fixtures(:braintree_blue)[:merchant_account_id], response.params["braintree_transaction"]["merchant_account_id"]
+ end
+
+ def test_successful_validate_on_store_with_verification_merchant_account
+ card = credit_card('4111111111111111', :verification_value => '101')
+ assert response = @gateway.store(card, :verify_card => true, :verification_merchant_account_id => fixtures(:braintree_blue)[:merchant_account_id])
+ assert_success response, "You must specify a valid :merchant_account_id key in your fixtures.yml for this to pass."
+ assert_equal 'OK', response.message
+ end
end
diff --git a/test/remote/gateways/remote_card_stream_modern_test.rb b/test/remote/gateways/remote_card_stream_modern_test.rb
index 3b65bd9b279..ea2ea0dbfc7 100644
--- a/test/remote/gateways/remote_card_stream_modern_test.rb
+++ b/test/remote/gateways/remote_card_stream_modern_test.rb
@@ -13,14 +13,6 @@ def setup
:brand => :american_express
)
- @uk_maestro = credit_card('6759015050123445002',
- :month => '12',
- :year => '2014',
- :issue_number => '0',
- :verification_value => '309',
- :brand => :switch
- )
-
@mastercard = credit_card('5301250070000191',
:month => '12',
:year => '2014',
@@ -93,17 +85,6 @@ def setup
:description => 'AM test purchase'
}
- @uk_maestro_options = {
- :billing_address => {
- :address1 => 'The Parkway',
- :address2 => "5258 Larches Approach",
- :city => "Hull",
- :state => "North Humberside",
- :zip => 'HU10 5OP'
- },
- :order_id => generate_unique_id,
- :description => 'AM test purchase'
- }
end
def test_successful_visacreditcard_authorization_and_capture
@@ -248,17 +229,11 @@ def test_declined_mastercard_purchase
def test_expired_mastercard
@mastercard.year = 2012
assert response = @gateway.purchase(142, @mastercard, @mastercard_options)
- assert_equal 'INVALID CARDEXPIRYDATE', response.message
+ assert_equal 'CARD EXPIRED', response.message
assert_failure response
assert response.test?
end
- def test_successful_maestro_purchase
- assert response = @gateway.purchase(142, @uk_maestro, @uk_maestro_options)
- assert_equal 'APPROVED', response.message
- assert_success response
- end
-
def test_successful_amex_purchase
assert response = @gateway.purchase(142, @amex, @amex_options)
assert_equal 'APPROVED', response.message
diff --git a/test/remote/gateways/remote_conekta_test.rb b/test/remote/gateways/remote_conekta_test.rb
new file mode 100644
index 00000000000..e6cdf914817
--- /dev/null
+++ b/test/remote/gateways/remote_conekta_test.rb
@@ -0,0 +1,119 @@
+require 'test_helper'
+
+class RemoteConektaTest < Test::Unit::TestCase
+ def setup
+ @gateway = ConektaGateway.new(fixtures(:conekta))
+
+ @amount = 300
+
+ @credit_card = ActiveMerchant::Billing::CreditCard.new(
+ number: "4111111111111111",
+ verification_value: "183",
+ month: "01",
+ year: "2018",
+ first_name: "Mario F.",
+ last_name: "Moreno Reyes"
+ )
+
+ @declined_card = ActiveMerchant::Billing::CreditCard.new(
+ number: "4000000000000002",
+ verification_value: "183",
+ month: "01",
+ year: "2018",
+ first_name: "Mario F.",
+ last_name: "Moreno Reyes"
+ )
+
+ @options = {
+ description: 'Blue clip',
+ address1: "Rio Missisipi #123",
+ address2: "Paris",
+ city: "Guerrero",
+ country: "Mexico",
+ zip: "5555",
+ name: "Mario Reyes",
+ phone: "12345678",
+ carrier: "Estafeta"
+ }
+ end
+
+ def test_successful_purchase
+ assert response = @gateway.purchase(@amount, @credit_card, @options)
+ assert_success response
+ assert_equal nil, response.message
+ end
+
+ def test_unsuccessful_purchase
+ assert response = @gateway.purchase(@amount, @declined_card, @options)
+ assert_failure response
+ assert_equal "The card was declined", response.message
+ end
+
+ def test_successful_refund
+ assert response = @gateway.purchase(@amount, @credit_card, @options)
+ @options[:order_id] = response.params["id"]
+ assert_success response
+ assert_equal nil, response.message
+
+ assert response = @gateway.refund(response.authorization, @amount, @options)
+ assert_success response
+ assert_equal nil, response.message
+ end
+
+ def test_unsuccessful_refund
+ assert response = @gateway.refund("1", @amount, @options)
+ assert_failure response
+ assert_equal "The charge does not exist or it is not suitable for this operation", response.message
+ end
+
+ def test_successful_authorize
+ assert response = @gateway.authorize(@amount, @credit_card, @options)
+ assert_success response
+ assert_equal nil, response.message
+ end
+
+ def test_unsuccessful_authorize
+ assert response = @gateway.authorize(@amount, @declined_card, @options)
+ assert_failure response
+ assert_equal "The card was declined", response.message
+ end
+
+ def test_successful_capture
+ assert response = @gateway.authorize(@amount, @credit_card, @options)
+ assert_success response
+ assert_equal nil, response.message
+
+ assert response = @gateway.capture(response.authorization, @amount, @options)
+ assert_success response
+ assert_equal nil, response.message
+ end
+
+ def test_successful_store
+ assert response = @gateway.store(@credit_card, {name: "John Doe", email: "email@example.com"})
+ assert_success response
+ assert_equal "customer", response.params["object"]
+ assert_equal "John Doe", response.params["name"]
+ assert_equal "email@example.com", response.params["email"]
+ end
+
+ def test_successful_unstore
+ creation = @gateway.store(@credit_card, {name: "John Doe", email: "email@example.com"})
+ assert response = @gateway.unstore(creation.params['id'])
+ assert_success response
+ assert_equal true, response.params["deleted"]
+ end
+
+ def test_unsuccessful_capture
+ @options[:order_id] = "1"
+ assert response = @gateway.capture(@amount, @options)
+ assert_failure response
+ assert_equal "The charge does not exist or it is not suitable for this operation", response.message
+ end
+
+ def test_invalid_login
+ gateway = ConektaGateway.new(key: 'invalid_token')
+ assert response = gateway.purchase(@amount, @credit_card, @options)
+ assert_failure response
+ assert_equal "Unrecognized authentication token", response.message
+ end
+end
diff --git a/test/remote/gateways/remote_eway_rapid_test.rb b/test/remote/gateways/remote_eway_rapid_test.rb
index 1cce2cf232a..1c26a3271d1 100644
--- a/test/remote/gateways/remote_eway_rapid_test.rb
+++ b/test/remote/gateways/remote_eway_rapid_test.rb
@@ -5,7 +5,7 @@ def setup
@gateway = EwayRapidGateway.new(fixtures(:eway_rapid))
@amount = 100
- @failed_amount = 105
+ @failed_amount = -100
@credit_card = credit_card("4444333322221111")
@options = {
@@ -19,7 +19,7 @@ def setup
def test_successful_purchase
assert response = @gateway.purchase(@amount, @credit_card, @options)
assert_success response
- assert_equal "Transaction Approved", response.message
+ assert_equal "Transaction Approved Successful", response.message
end
def test_fully_loaded_purchase
@@ -27,6 +27,7 @@ def test_fully_loaded_purchase
:redirect_url => "http://awesomesauce.com",
:ip => "0.0.0.0",
:application_id => "Woohoo",
+ :transaction_type => "Purchase",
:description => "Description",
:order_id => "orderid1",
:currency => "AUD",
@@ -64,49 +65,61 @@ def test_fully_loaded_purchase
def test_failed_purchase
assert response = @gateway.purchase(@failed_amount, @credit_card, @options)
assert_failure response
- assert_equal "Do Not Honour", response.message
+ assert_equal "Invalid Payment TotalAmount", response.message
end
- def test_failed_setup_purchase
- assert response = @gateway.setup_purchase(@amount, :redirect_url => "")
- assert_failure response
- assert_equal "V6047", response.message
- end
-
- def test_failed_run_purchase
- setup_response = @gateway.setup_purchase(@amount, @options)
- assert_success setup_response
+ def test_successful_refund
+ # purchase
+ assert response = @gateway.purchase(@amount, @credit_card, @options)
+ assert_success response
+ assert_equal "Transaction Approved Successful", response.message
- assert response = @gateway.send(:run_purchase, "bogus", @credit_card, setup_response.params["formactionurl"])
- assert_failure response
- assert_match(%r{Access Code Invalid}, response.message)
+ # refund
+ assert response = @gateway.refund(@amount, response.authorization, @options)
+ assert_success response
+ assert_equal "Transaction Approved Successful", response.message
end
- def test_failed_status
- setup_response = @gateway.setup_purchase(@failed_amount, @options)
- assert_success setup_response
-
- assert run_response = @gateway.send(:run_purchase, setup_response.authorization, @credit_card, setup_response.params["formactionurl"])
- assert_success run_response
-
- response = @gateway.status(run_response.authorization)
+ def test_failed_refund
+ assert response = @gateway.refund(@amount, 'fakeid', @options)
assert_failure response
- assert_equal "Do Not Honour", response.message
- assert_equal run_response.authorization, response.authorization
+ assert_equal "System Error", response.message
end
def test_successful_store
@options[:billing_address].merge!(:title => "Dr.")
assert response = @gateway.store(@credit_card, @options)
assert_success response
- assert_equal "Transaction Approved", response.message
+ assert_equal "Transaction Approved Successful", response.message
end
def test_failed_store
@options[:billing_address].merge!(:country => nil)
assert response = @gateway.store(@credit_card, @options)
assert_failure response
- assert_equal "V6044", response.message
+ assert_equal "V6044", response.params["Errors"]
+ assert_equal "Customer CountryCode Required", response.message
+ end
+
+ def test_successful_update
+ @options[:billing_address].merge!(:title => "Dr.")
+ assert response = @gateway.store(@credit_card, @options)
+ assert_success response
+ assert_equal "Transaction Approved Successful", response.message
+ assert response = @gateway.update(response.authorization, @credit_card, @options)
+ assert_success response
+ assert_equal "Transaction Approved Successful", response.message
+ end
+
+ def test_successful_store_purchase
+ @options[:billing_address].merge!(:title => "Dr.")
+ assert response = @gateway.store(@credit_card, @options)
+ assert_success response
+ assert_equal "Transaction Approved Successful", response.message
+
+ assert response = @gateway.purchase(@amount, response.authorization, {transaction_type: 'MOTO'})
+ assert_success response
+ assert_equal "Transaction Approved Successful", response.message
end
def test_invalid_login
diff --git a/test/remote/gateways/remote_merchant_warrior_test.rb b/test/remote/gateways/remote_merchant_warrior_test.rb
index dadef6c86a4..da81661c4ef 100644
--- a/test/remote/gateways/remote_merchant_warrior_test.rb
+++ b/test/remote/gateways/remote_merchant_warrior_test.rb
@@ -16,7 +16,7 @@ def setup
)
@options = {
- :address => {
+ :billing_address => {
:name => 'Longbob Longsen',
:country => 'AU',
:state => 'Queensland',
@@ -24,7 +24,7 @@ def setup
:address1 => '123 test st',
:zip => '4000'
},
- :transaction_product => 'TestProduct'
+ :description => 'TestProduct'
}
end
diff --git a/test/remote/gateways/remote_mercury_test.rb b/test/remote/gateways/remote_mercury_test.rb
index 5fda0efb03c..254b4793f7a 100644
--- a/test/remote/gateways/remote_mercury_test.rb
+++ b/test/remote/gateways/remote_mercury_test.rb
@@ -71,6 +71,14 @@ def test_successful_purchase
assert_equal "0.50", response.params["purchase"]
end
+ def test_store
+ response = @gateway.store(@credit_card, @options)
+
+ assert_success response
+ assert response.params.has_key?("record_no")
+ assert response.params['record_no'] != ''
+ end
+
def test_credit
response = @gateway.credit(50, @credit_card, @options)
diff --git a/test/remote/gateways/remote_pac_net_raven_test.rb b/test/remote/gateways/remote_pac_net_raven_test.rb
new file mode 100644
index 00000000000..2f213280180
--- /dev/null
+++ b/test/remote/gateways/remote_pac_net_raven_test.rb
@@ -0,0 +1,207 @@
+require 'test_helper'
+
+class RemotePacNetRavenGatewayTest < Test::Unit::TestCase
+ def setup
+ @gateway = PacNetRavenGateway.new(fixtures(:raven_pac_net))
+
+ @amount = 100
+ @credit_card = credit_card('4000000000000028')
+ @declined_card = credit_card('5100000000000040')
+
+ @options = {
+ billing_address: address
+ }
+ end
+
+ def test_successful_purchase
+ assert purchase = @gateway.purchase(@amount, @credit_card, @options)
+ assert_success purchase
+ assert purchase.params['ApprovalCode']
+ assert purchase.params['TrackingNumber']
+ assert_nil purchase.params['ErrorCode']
+ assert_equal 'Approved', purchase.params['Status']
+ assert_equal 'ok', purchase.params['RequestResult']
+ assert_nil purchase.params['Message']
+ assert_equal 'This transaction has been approved', purchase.message
+ end
+
+ def test_invalid_credit_card_number_purchese
+ @credit_card = credit_card('0000')
+ assert purchase = @gateway.purchase(@amount, @credit_card, @options)
+ assert_failure purchase
+ assert_nil purchase.params['ApprovalCode']
+ assert purchase.params['TrackingNumber']
+ assert_equal 'invalid:cardNumber', purchase.params['ErrorCode']
+ assert_equal 'Invalid:CardNumber', purchase.params['Status']
+ assert_equal 'ok', purchase.params['RequestResult']
+ assert_equal "Error processing transaction because CardNumber \"0000\" is not between 12 and 19 in length.", purchase.params['Message']
+ end
+
+ def test_expired_credit_card_purchese
+ @credit_card.month = 9
+ @credit_card.year = 2012
+ assert purchase = @gateway.purchase(@amount, @credit_card, @options)
+ assert_failure purchase
+ assert_nil purchase.params['ApprovalCode']
+ assert purchase.params['TrackingNumber']
+ assert_equal 'invalid:CustomerCardExpiryDate', purchase.params['ErrorCode']
+ assert_equal 'Invalid:CustomerCardExpiryDate', purchase.params['Status']
+ assert_equal 'ok', purchase.params['RequestResult']
+ assert_equal "Invalid because the card expiry date (mmyy) \"0912\" is not a date in the future", purchase.params['Message']
+ end
+
+ def test_declined_purchese
+ assert purchase = @gateway.purchase(@amount, @declined_card, @options)
+ assert_failure purchase
+ assert_equal 'RepeatDeclined', purchase.message
+ end
+
+ def test_successful_authorization
+ assert auth = @gateway.authorize(@amount, @credit_card, @options)
+ assert_success auth
+ assert auth.params['ApprovalCode']
+ assert auth.params['TrackingNumber']
+ assert_nil auth.params['ErrorCode']
+ assert_nil auth.params['Message']
+ assert_equal 'Approved', auth.params['Status']
+ assert_equal 'ok', auth.params['RequestResult']
+ assert_equal 'This transaction has been approved', auth.message
+ end
+
+ def test_invalid_credit_card_number_authorization
+ @credit_card = credit_card('0000')
+ assert auth = @gateway.authorize(@amount, @credit_card, @options)
+ assert_failure auth
+ assert_nil auth.params['ApprovalCode']
+ assert auth.params['TrackingNumber']
+ assert_equal 'invalid:cardNumber', auth.params['ErrorCode']
+ assert_equal 'Invalid:CardNumber', auth.params['Status']
+ assert_equal 'ok', auth.params['RequestResult']
+ assert_equal "Error processing transaction because CardNumber \"0000\" is not between 12 and 19 in length.", auth.params['Message']
+ end
+
+ def test_expired_credit_card_authorization
+ @credit_card.month = 9
+ @credit_card.year = 2012
+ assert auth = @gateway.authorize(@amount, @credit_card, @options)
+ assert_failure auth
+ assert_nil auth.params['ApprovalCode']
+ assert auth.params['TrackingNumber']
+ assert_equal 'invalid:CustomerCardExpiryDate', auth.params['ErrorCode']
+ assert_equal 'Invalid:CustomerCardExpiryDate', auth.params['Status']
+ assert_equal 'ok', auth.params['RequestResult']
+ assert_equal "Invalid because the card expiry date (mmyy) \"0912\" is not a date in the future", auth.params['Message']
+ end
+
+ def test_declined_authorization
+ assert auth = @gateway.authorize(@amount, @declined_card, @options)
+ assert_failure auth
+ assert_equal 'RepeatDeclined', auth.message
+ end
+
+ def test_successful_refund
+ assert purchase = @gateway.purchase(@amount, @credit_card, @options)
+ assert refund = @gateway.refund(@amount, purchase.authorization)
+ assert_success refund
+ assert refund.params['ApprovalCode']
+ assert refund.params['TrackingNumber']
+ assert_nil refund.params['ErrorCode']
+ assert_equal 'Approved', refund.params['Status']
+ assert_equal 'ok', refund.params['RequestResult']
+ assert_nil refund.params['Message']
+ assert_equal 'This transaction has been approved', refund.message
+ end
+
+ def test_amount_greater_than_original_amount_refund
+ assert purchase = @gateway.purchase(100, @credit_card, @options)
+ assert_success purchase
+
+ assert refund = @gateway.refund(200, purchase.authorization)
+ assert_failure refund
+ assert_nil refund.params['ApprovalCode']
+ assert refund.params['TrackingNumber']
+ assert_equal 'invalid:RefundAmountGreaterThanOriginalAmount', refund.params['ErrorCode']
+ assert_equal 'Invalid:RefundAmountGreaterThanOriginalAmount', refund.params['Status']
+ assert_equal 'ok', refund.params['RequestResult']
+ assert_equal "Invalid because the payment amount cannot be greater than the original charge.", refund.params['Message']
+ assert_equal 'Invalid because the payment amount cannot be greater than the original charge.', refund.message
+ end
+
+ def test_purchase_and_void
+ purchase = @gateway.purchase(@amount, @credit_card, @options)
+ assert void = @gateway.void(purchase.authorization, {:pymt_type => purchase.params['PymtType']})
+ assert_success void
+ assert void.params['ApprovalCode']
+ assert void.params['TrackingNumber']
+ assert_nil void.params['ErrorCode']
+ assert_equal 'ok', void.params['RequestResult']
+ assert_nil void.params['Message']
+ assert_equal 'Voided', void.params['Status']
+ assert_equal "This transaction has been voided", void.message
+ end
+
+ def test_authorize_and_void
+ auth = @gateway.authorize(@amount, @credit_card, @options)
+ assert void = @gateway.void(auth.authorization)
+ assert_failure void
+ assert void.params['ApprovalCode']
+ assert void.params['TrackingNumber']
+ assert_equal 'error:canNotBeVoided', void.params['ErrorCode']
+ assert_equal 'ok', void.params['RequestResult']
+ assert_equal "Error processing transaction because the payment may not be voided.", void.params['Message']
+ assert_equal 'Approved', void.params['Status']
+ assert_equal "Error processing transaction because the payment may not be voided.", void.message
+ end
+
+ def test_authorize_capture_and_void
+ auth = @gateway.authorize(@amount, @credit_card, @options)
+ assert capture = @gateway.capture(@amount, auth.authorization)
+ assert void = @gateway.void(capture.authorization, {:pymt_type => capture.params['PymtType']})
+ assert_failure void
+ assert void.params['ApprovalCode']
+ assert void.params['TrackingNumber']
+ assert_equal 'error:canNotBeVoided', void.params['ErrorCode']
+ assert_equal 'ok', void.params['RequestResult']
+ assert_equal "Error processing transaction because the payment may not be voided.", void.params['Message']
+ assert_equal 'Approved', void.params['Status']
+ assert_equal "Error processing transaction because the payment may not be voided.", void.message
+ end
+
+ def test_successful_capture
+ auth = @gateway.authorize(@amount, @credit_card, @options)
+ assert capture = @gateway.capture(@amount, auth.authorization)
+ assert_success capture
+ assert capture.params['ApprovalCode']
+ assert capture.params['TrackingNumber']
+ assert_nil capture.params['ErrorCode']
+ assert_equal 'Approved', capture.params['Status']
+ assert_equal 'ok', capture.params['RequestResult']
+ assert_nil capture.params['Message']
+ assert_equal 'This transaction has been approved', capture.message
+ end
+
+ def test_invalid_preauth_number_capture
+ assert capture = @gateway.capture(@amount, '')
+ assert_failure capture
+ assert_nil capture.params['ApprovalCode']
+ assert capture.params['TrackingNumber']
+ assert_equal 'invalid:PreAuthNumber', capture.params['ErrorCode']
+ assert_equal 'Invalid:PreauthNumber', capture.params['Status']
+ assert_equal 'ok', capture.params['RequestResult']
+ assert_equal "Error processing transaction because the pre-auth number \"0\" does not correspond to a pre-existing payment.", capture.params['Message']
+ assert capture.message.include?('Error processing transaction because the pre-auth number')
+ end
+
+ def test_insufficient_preauth_amount_capture
+ auth = @gateway.authorize(100, @credit_card, @options)
+ assert capture = @gateway.capture(200, auth.authorization)
+ assert_failure capture
+ assert_nil capture.params['ApprovalCode']
+ assert capture.params['TrackingNumber']
+ assert_equal 'rejected:PreauthAmountInsufficient', capture.params['ErrorCode']
+ assert_equal 'Rejected:PreauthAmountInsufficient', capture.params['Status']
+ assert_equal 'ok', capture.params['RequestResult']
+ assert_equal "Invalid because the preauthorization amount 100 is insufficient", capture.params['Message']
+ assert_equal 'Invalid because the preauthorization amount 100 is insufficient', capture.message
+ end
+end
diff --git a/test/remote/gateways/remote_pay_junction_test.rb b/test/remote/gateways/remote_pay_junction_test.rb
index db8724e1811..4744ea59995 100644
--- a/test/remote/gateways/remote_pay_junction_test.rb
+++ b/test/remote/gateways/remote_pay_junction_test.rb
@@ -98,7 +98,7 @@ def test_successful_void
end
def test_successful_instant_purchase
- # this takes advatange of the PayJunction feature where another
+ # this takes advantage of the PayJunction feature where another
# transaction can be executed if you have the transaction ID of a
# previous successful transaction.
diff --git a/test/remote/gateways/remote_payex_test.rb b/test/remote/gateways/remote_payex_test.rb
new file mode 100644
index 00000000000..5483a8f1eda
--- /dev/null
+++ b/test/remote/gateways/remote_payex_test.rb
@@ -0,0 +1,120 @@
+require 'test_helper'
+
+class RemotePayexTest < Test::Unit::TestCase
+
+ def setup
+ @gateway = PayexGateway.new(fixtures(:payex))
+
+ @amount = 1000
+ # cvv 210, expire date 02/14
+ @credit_card = credit_card('4581090329655682', verification_value: 210, month: 2, year: 14)
+ @declined_card = credit_card('4000300011112220')
+
+ @options = {
+ :order_id => '1234',
+ }
+ end
+
+ def test_successful_purchase
+ assert response = @gateway.purchase(@amount, @credit_card, @options)
+ assert_success response
+ assert_equal 'OK', response.message
+ end
+
+ def test_unsuccessful_purchase
+ assert response = @gateway.purchase(@amount, @declined_card, @options)
+ assert_failure response
+ # we can't test for a message since the messages vary so much
+ assert_not_equal 'OK', response.message
+ end
+
+ def test_authorize_and_capture
+ amount = @amount
+ assert response = @gateway.authorize(amount, @credit_card, @options)
+ assert_success response
+ assert_equal 'OK', response.message
+
+ assert response.authorization
+ assert response = @gateway.capture(amount, response.authorization)
+ assert_success response
+ end
+
+ def test_failed_capture
+ assert response = @gateway.capture(@amount, '1')
+ assert_failure response
+ assert_not_equal 'OK', response.message
+ assert_not_equal 'RecordNotFound', response.params[:status_errorcode]
+ end
+
+ def test_authorization_and_void
+ assert response = @gateway.authorize(@amount, @credit_card, @options)
+ assert_success response
+
+ assert response = @gateway.void(response.authorization)
+ assert_success response
+ end
+
+ def test_unsuccessful_void
+ assert response = @gateway.void("1")
+ assert_failure response
+ assert_not_equal 'OK', response.message
+ assert_match /1/, response.message
+ end
+
+ def test_successful_refund
+ assert response = @gateway.purchase(@amount, @credit_card, @options)
+ assert_success response
+ assert response.authorization
+ assert response = @gateway.refund(@amount - 200, response.authorization, order_id: '123')
+ assert_success response
+ end
+
+ def test_unsuccessful_refund
+ assert response = @gateway.refund(@amount, "1", order_id: '123')
+ assert_failure response
+ assert_not_equal 'OK', response.message
+ assert_match /1/, response.message
+ end
+
+ def test_successful_store_and_purchase
+ assert response = @gateway.store(@credit_card, @options)
+ assert_success response
+ assert_equal 'OK', response.message
+
+ assert response = @gateway.purchase(@amount, response.authorization, @options.merge({order_id: '5678'}))
+ assert_success response
+ assert_equal 'OK', response.message
+ end
+
+ def test_successful_store_and_authorize_and_capture
+ assert response = @gateway.store(@credit_card, @options)
+ assert_success response
+ assert_equal 'OK', response.message
+
+ assert response = @gateway.authorize(@amount, response.authorization, @options.merge({order_id: '5678'}))
+ assert_success response
+ assert_equal 'OK', response.message
+ assert response.authorization
+
+ assert response = @gateway.capture(@amount, response.authorization)
+ assert_success response
+ end
+
+ def test_successful_unstore
+ assert response = @gateway.store(@credit_card, @options)
+ assert_equal 'OK', response.message
+ assert response = @gateway.unstore(response.authorization)
+ assert_success response
+ assert_equal 'OK', response.message
+ end
+
+ def test_invalid_login
+ gateway = PayexGateway.new(
+ :account => '1',
+ :encryption_key => '1'
+ )
+ assert response = gateway.purchase(@amount, @credit_card, @options)
+ assert_failure response
+ assert_not_equal 'OK', response.message
+ end
+end
diff --git a/test/remote/gateways/remote_payflow_test.rb b/test/remote/gateways/remote_payflow_test.rb
index b3d49a939d3..0622c7957fd 100644
--- a/test/remote/gateways/remote_payflow_test.rb
+++ b/test/remote/gateways/remote_payflow_test.rb
@@ -5,17 +5,24 @@ def setup
ActiveMerchant::Billing::Base.gateway_mode = :test
@gateway = PayflowGateway.new(fixtures(:payflow))
-
- @credit_card = credit_card('5105105105105100',
+
+ @credit_card = credit_card(
+ '5105105105105100',
:brand => 'master'
)
- @options = { :billing_address => address,
- :email => 'cody@example.com',
- :customer => 'codyexample'
- }
+ @options = {
+ :billing_address => address,
+ :email => 'cody@example.com',
+ :customer => 'codyexample'
+ }
+
+ @check = check(
+ :routing_number => '111111118',
+ :account_number => '1234567801'
+ )
end
-
+
def test_successful_purchase
assert response = @gateway.purchase(100000, @credit_card, @options)
assert_equal "Approved", response.message
@@ -23,14 +30,28 @@ def test_successful_purchase
assert response.test?
assert_not_nil response.authorization
end
-
+
def test_declined_purchase
assert response = @gateway.purchase(210000, @credit_card, @options)
assert_equal 'Declined', response.message
assert_failure response
assert response.test?
end
-
+
+ # Additional steps are required to enable ACH in a Payflow Pro account.
+ # See the "Payflow ACH Payment Service Guide" for more details:
+ # http://www.paypalobjects.com/webstatic/en_US/developer/docs/pdf/pp_achpayment_guide.pdf
+ #
+ # Also, when testing against the pilot-payflowpro.paypal.com endpoint, ACH must be enabled by Payflow support.
+ # This can be accomplished by sending an email to payflow-support@paypal.com with your Merchant Login.
+ def test_successful_ach_purchase
+ assert response = @gateway.purchase(50, @check)
+ assert_equal "Approved", response.message
+ assert_success response
+ assert response.test?
+ assert_not_nil response.authorization
+ end
+
def test_successful_authorization
assert response = @gateway.authorize(100, @credit_card, @options)
assert_equal "Approved", response.message
@@ -47,23 +68,23 @@ def test_authorize_and_capture
assert capture = @gateway.capture(100, auth.authorization)
assert_success capture
end
-
+
def test_authorize_and_partial_capture
assert auth = @gateway.authorize(100 * 2, @credit_card, @options)
assert_success auth
assert_equal 'Approved', auth.message
assert auth.authorization
-
+
assert capture = @gateway.capture(100, auth.authorization)
assert_success capture
end
-
+
def test_failed_capture
assert response = @gateway.capture(100, '999')
assert_failure response
assert_equal 'Invalid tender', response.message
end
-
+
def test_authorize_and_void
assert auth = @gateway.authorize(100, @credit_card, @options)
assert_success auth
@@ -72,7 +93,7 @@ def test_authorize_and_void
assert void = @gateway.void(auth.authorization)
assert_success void
end
-
+
def test_invalid_login
gateway = PayflowGateway.new(
:login => '',
@@ -82,27 +103,27 @@ def test_invalid_login
assert_equal 'Invalid vendor account', response.message
assert_failure response
end
-
+
def test_duplicate_request_id
request_id = Digest::MD5.hexdigest(rand.to_s)
@gateway.expects(:generate_unique_id).times(2).returns(request_id)
-
+
response1 = @gateway.purchase(100, @credit_card, @options)
assert response1.success?
assert_nil response1.params['duplicate']
-
+
response2 = @gateway.purchase(100, @credit_card, @options)
assert response2.success?
assert response2.params['duplicate']
end
-
+
def test_create_recurring_profile
response = @gateway.recurring(1000, @credit_card, :periodicity => :monthly)
assert_success response
assert !response.params['profile_id'].blank?
assert response.test?
end
-
+
def test_create_recurring_profile_with_invalid_date
response = @gateway.recurring(1000, @credit_card, :periodicity => :monthly, :starting_at => Time.now)
assert_failure response
@@ -110,18 +131,18 @@ def test_create_recurring_profile_with_invalid_date
assert response.params['profile_id'].blank?
assert response.test?
end
-
+
def test_create_and_cancel_recurring_profile
response = @gateway.recurring(1000, @credit_card, :periodicity => :monthly)
assert_success response
assert !response.params['profile_id'].blank?
assert response.test?
-
+
response = @gateway.cancel_recurring(response.params['profile_id'])
assert_success response
assert response.test?
end
-
+
def test_full_feature_set_for_recurring_profiles
# Test add
@options.update(
@@ -137,7 +158,7 @@ def test_full_feature_set_for_recurring_profiles
assert response.test?
assert !response.params['profile_id'].blank?
@recurring_profile_id = response.params['profile_id']
-
+
# Test modify
@options.update(
:periodicity => :monthly,
@@ -150,19 +171,19 @@ def test_full_feature_set_for_recurring_profiles
assert_equal "0", response.params['result']
assert_success response
assert response.test?
-
+
# Test inquiry
- response = @gateway.recurring_inquiry(@recurring_profile_id)
+ response = @gateway.recurring_inquiry(@recurring_profile_id)
assert_equal "0", response.params['result']
assert_success response
assert response.test?
-
+
# Test payment history inquiry
response = @gateway.recurring_inquiry(@recurring_profile_id, :history => true)
assert_equal '0', response.params['result']
assert_success response
assert response.test?
-
+
# Test cancel
response = @gateway.cancel_recurring(@recurring_profile_id)
assert_equal "Approved", response.params['message']
@@ -170,7 +191,7 @@ def test_full_feature_set_for_recurring_profiles
assert_success response
assert response.test?
end
-
+
# Note that this test will only work if you enable reference transactions!!
def test_reference_purchase
assert response = @gateway.purchase(10000, @credit_card, @options)
@@ -178,60 +199,68 @@ def test_reference_purchase
assert_success response
assert response.test?
assert_not_nil pn_ref = response.authorization
-
+
# now another purchase, by reference
assert response = @gateway.purchase(10000, pn_ref)
assert_equal "Approved", response.message
assert_success response
assert response.test?
end
-
+
def test_recurring_with_initial_authorization
- response = @gateway.recurring(1000, @credit_card,
+ response = @gateway.recurring(1000, @credit_card,
:periodicity => :monthly,
:initial_transaction => {
- :brand => :authorization
+ :type => :authorization
}
)
-
+
assert_success response
assert !response.params['profile_id'].blank?
assert response.test?
end
-
+
def test_recurring_with_initial_authorization
- response = @gateway.recurring(1000, @credit_card,
+ response = @gateway.recurring(1000, @credit_card,
:periodicity => :monthly,
:initial_transaction => {
- :brand => :purchase,
+ :type => :purchase,
:amount => 500
}
)
-
+
assert_success response
assert !response.params['profile_id'].blank?
assert response.test?
end
-
- def test_purchase_and_referenced_credit
+
+ def test_purchase_and_refund
amount = 100
-
+
assert purchase = @gateway.purchase(amount, @credit_card, @options)
assert_success purchase
assert_equal 'Approved', purchase.message
assert !purchase.authorization.blank?
-
- assert credit = @gateway.credit(amount, purchase.authorization)
+
+ assert credit = @gateway.refund(amount, purchase.authorization)
assert_success credit
end
-
- # The default security setting for Payflow Pro accounts is Allow
+
+ # The default security setting for Payflow Pro accounts is Allow
# non-referenced credits = No.
#
- # Non-referenced credits will fail with Result code 117 (failed the security
+ # Non-referenced credits will fail with Result code 117 (failed the security
# check) unless Allow non-referenced credits = Yes in PayPal manager
- def test_purchase_and_non_referenced_credit
+ def test_purchase_and_credit
assert credit = @gateway.credit(100, @credit_card, @options)
assert_success credit
end
+
+ def test_successful_ach_credit
+ assert response = @gateway.credit(50, @check)
+ assert_equal "Approved", response.message
+ assert_success response
+ assert response.test?
+ assert_not_nil response.authorization
+ end
end
diff --git a/test/remote/gateways/remote_paymill_test.rb b/test/remote/gateways/remote_paymill_test.rb
index c4189267bc2..68c01b2e849 100644
--- a/test/remote/gateways/remote_paymill_test.rb
+++ b/test/remote/gateways/remote_paymill_test.rb
@@ -5,31 +5,44 @@ def setup
@gateway = PaymillGateway.new(fixtures(:paymill))
@amount = 100
- @credit_card = credit_card('5105105105105100')
+ @credit_card = credit_card('5500000000000004')
+ @declined_card = credit_card('5105105105105100', month: 5, year: 2020)
end
def test_successful_purchase
assert response = @gateway.purchase(@amount, @credit_card)
assert_success response
- assert_equal 'Transaction approved', response.message
+ assert_equal 'General success response.', response.message
end
- def test_failed_purchase_with_invalid_card
+ def test_failed_store_card_attempting_purchase
@credit_card.number = ''
assert response = @gateway.purchase(@amount, @credit_card)
assert_failure response
assert_equal 'Account or Bank Details Incorrect', response.message
end
+ def test_failed_purchase
+ assert response = @gateway.purchase(@amount, @declined_card)
+ assert_failure response
+ assert_equal 'Card declined by authorization system.', response.message
+ end
+
def test_successful_authorize_and_capture
assert response = @gateway.authorize(@amount, @credit_card)
assert_success response
- assert_equal 'Transaction approved', response.message
+ assert_equal 'General success response.', response.message
assert response.authorization
assert capture_response = @gateway.capture(@amount, response.authorization)
assert_success capture_response
- assert_equal 'Transaction approved', capture_response.message
+ assert_equal 'General success response.', capture_response.message
+ end
+
+ def test_failed_authorize
+ assert response = @gateway.authorize(@amount, @declined_card)
+ assert_failure response
+ assert_equal 'Card declined by authorization system.', response.message
end
def test_failed_capture
@@ -47,12 +60,12 @@ def test_failed_capture
def test_successful_authorize_and_void
assert response = @gateway.authorize(@amount, @credit_card)
assert_success response
- assert_equal 'Transaction approved', response.message
+ assert_equal 'General success response.', response.message
assert response.authorization
assert void_response = @gateway.void(response.authorization)
assert_success void_response
- assert_equal 'Transaction approved', void_response.message
+ assert_equal 'Transaction approved.', void_response.message
end
def test_successful_refund
@@ -62,7 +75,7 @@ def test_successful_refund
assert refund = @gateway.refund(@amount, response.authorization)
assert_success refund
- assert_equal 'Transaction approved', refund.message
+ assert_equal 'General success response.', refund.message
end
def test_failed_refund
@@ -107,10 +120,4 @@ def test_successful_store_and_authorize
assert_success authorize
end
- # Paymill doesn't yet offer a way to trigger a decline on a test account.
- # def test_failed_purchase_with_declined_credit_card
- # assert response = @gateway.purchase(@amount, @declined_card)
- # assert_failure response
- # assert_equal 'Unable to process the purchase transaction.', response.message
- # end
end
diff --git a/test/remote/gateways/remote_payscout_test.rb b/test/remote/gateways/remote_payscout_test.rb
new file mode 100644
index 00000000000..e3ad29ce708
--- /dev/null
+++ b/test/remote/gateways/remote_payscout_test.rb
@@ -0,0 +1,160 @@
+require 'test_helper'
+
+class RemotePayscoutTest < Test::Unit::TestCase
+ def setup
+ @gateway = PayscoutGateway.new(fixtures(:payscout))
+
+ @amount = 100
+ @credit_card = credit_card('4111111111111111', verification_value: 999)
+ @declined_card = credit_card('34343')
+
+ @options = {
+ :order_id => '1',
+ :description => 'Store Purchase',
+ :billing_address => address
+ }
+ end
+
+ ########## Purchase ##########
+
+ def test_cvv_fail_purchase
+ @credit_card = credit_card('4111111111111111')
+ assert response = @gateway.purchase(@amount, @credit_card, @options)
+
+
+ assert_success response
+ assert_equal 'The transaction has been approved', response.message
+ assert_equal 'N', response.cvv_result['code']
+ end
+
+
+ def test_approved_purchase
+ assert response = @gateway.purchase(@amount, @credit_card, @options)
+ assert_success response
+ assert_equal 'The transaction has been approved', response.message
+ end
+
+ def test_declined_purchase
+ @amount = 60
+ assert response = @gateway.purchase(@amount, @credit_card, @options)
+ assert_failure response
+ assert_equal 'The transaction has been declined', response.message
+ end
+
+ ########## Authorize ##########
+
+ def test_approved_authorization
+ assert response = @gateway.authorize(@amount, @credit_card, @options)
+ assert_success response
+ assert_equal 'The transaction has been approved', response.message
+ end
+
+ def test_declined_authorization
+ @amount = 60
+ assert response = @gateway.authorize(@amount, @credit_card, @options)
+ assert_failure response
+ assert_equal 'The transaction has been declined', response.message
+ end
+
+ ########## Capture ##########
+
+ def test_approved_capture
+ amount = @amount
+ assert auth = @gateway.authorize(amount, @credit_card, @options)
+ assert_success auth
+ assert_equal 'The transaction has been approved', auth.message
+ assert auth.authorization
+ assert capture = @gateway.capture(amount, auth.authorization)
+ assert_success capture
+ end
+
+ def test_invalid_amount_capture
+ amount = @amount
+ assert auth = @gateway.authorize(amount, @credit_card, @options)
+ assert_success auth
+ assert_equal 'The transaction has been approved', auth.message
+ assert auth.authorization
+ amount = 200
+ assert capture = @gateway.capture(amount, auth.authorization)
+ assert_failure capture
+ assert_match 'The specified amount of 2.00 exceeds the authorization amount of 1.00', capture.message
+ end
+
+ def test_not_found_transaction_id_capture
+ assert capture = @gateway.capture(@amount, '1234567890')
+ assert_failure capture
+ assert_match 'Transaction not found', capture.message
+ end
+
+ def test_invalid_transaction_id_capture
+ assert capture = @gateway.capture(@amount, '')
+ assert_failure capture
+ assert_match 'Invalid Transaction ID', capture.message
+ end
+
+ ########## Refund ##########
+
+ def test_approved_refund
+ purchase = @gateway.purchase(@amount, @credit_card, @options)
+ assert refund = @gateway.refund(@amount, purchase.authorization)
+ assert_success refund
+ assert_equal "The transaction has been approved", refund.message
+ end
+
+ def test_not_found_transaction_id_refund
+ assert refund = @gateway.refund(@amount, '1234567890')
+ assert_failure refund
+ assert_match "Transaction not found", refund.message
+ end
+
+ def test_invalid_transaction_id_refund
+ assert refund = @gateway.refund(@amount, '')
+ assert_failure refund
+ assert_match "Invalid Transaction ID", refund.message
+ end
+
+ def test_invalid_amount_refund
+ purchase = @gateway.purchase(@amount, @credit_card, @options)
+ assert refund = @gateway.refund(200, purchase.authorization)
+ assert_failure refund
+ assert_match "Refund amount may not exceed the transaction balance", refund.message
+ end
+
+ ########## Void ##########
+
+ def test_approved_void_purchase
+ purchase = @gateway.purchase(@amount, @credit_card, @options)
+ assert void = @gateway.void(purchase.authorization)
+ assert_success void
+ assert_equal "The transaction has been approved", void.message
+ end
+
+ def test_approved_void_authorization
+ auth = @gateway.authorize(@amount, @credit_card, @options)
+ assert void = @gateway.void(auth.authorization)
+ assert_success void
+ assert_equal "The transaction has been approved", void.message
+ end
+
+ def test_invalid_transaction_id_void
+ assert void = @gateway.void('')
+ assert_failure void
+ assert_match "Invalid Transaction ID", void.message
+ end
+
+ def test_not_found_transaction_id_void
+ assert void = @gateway.void('1234567890')
+ assert_failure void
+ assert_match "Transaction not found", void.message
+ end
+
+ def test_invalid_credentials
+ gateway = PayscoutGateway.new(
+ :username => 'xxx',
+ :password => 'xxx'
+ )
+ assert response = gateway.purchase(@amount, @credit_card, @options)
+ assert_failure response
+ assert_equal 'Authentication Failed', response.message
+ end
+end
diff --git a/test/remote/gateways/remote_paystation_test.rb b/test/remote/gateways/remote_paystation_test.rb
index 40b3a732080..b3277889c34 100644
--- a/test/remote/gateways/remote_paystation_test.rb
+++ b/test/remote/gateways/remote_paystation_test.rb
@@ -78,7 +78,7 @@ def test_authorize_and_capture
end
def test_capture_without_cvv
- # for some merchant accounts, paystation requires you send through the card vertification value
+ # for some merchant accounts, paystation requires you send through the card verification value
# on a capture request
assert auth = @gateway.authorize(@successful_amount, @credit_card, @options.merge(:order_id => get_uid))
diff --git a/test/remote/gateways/remote_so_easy_pay_test.rb b/test/remote/gateways/remote_so_easy_pay_test.rb
new file mode 100644
index 00000000000..8803620f610
--- /dev/null
+++ b/test/remote/gateways/remote_so_easy_pay_test.rb
@@ -0,0 +1,66 @@
+require 'test_helper'
+
+class RemoteSoEasyPayTest < Test::Unit::TestCase
+
+
+ def setup
+ @gateway = SoEasyPayGateway.new(fixtures(:so_easy_pay))
+
+ @amount = 100
+ @credit_card = credit_card('4111111111111111', {:verification_value => '000', :month => '12', :year => '2015'})
+ @declined_card = credit_card('4000300011112220')
+
+ @options = {
+ :currency => 'EUR',
+ :ip => '192.168.19.123',
+ :email => 'test@blaha.com',
+ :order_id => generate_unique_id,
+ :billing_address => address,
+ :description => 'Store Purchase'
+ }
+ end
+
+ def test_successful_purchase
+ assert response = @gateway.purchase(@amount, @credit_card, @options)
+ assert_success response
+ assert_equal 'Transaction successful', response.message
+ end
+
+ def test_unsuccessful_purchase
+ assert response = @gateway.purchase(@amount, @declined_card, @options)
+ assert_failure response
+ end
+
+ def test_authorize_and_capture
+ amount = @amount
+ assert auth = @gateway.authorize(amount, @credit_card, @options)
+ assert_success auth
+ assert auth.authorization
+ assert capture = @gateway.capture(amount, auth.authorization)
+ assert_success capture
+ end
+
+ def test_failed_capture
+ assert response = @gateway.capture(@amount, '')
+ assert_failure response
+ end
+
+ def test_successful_void
+ assert response = @gateway.purchase(@amount, @credit_card, @options)
+ assert_success response
+
+ assert response = @gateway.void(response.authorization)
+ assert_success response
+ end
+
+ def test_invalid_login
+ gateway = SoEasyPayGateway.new(
+ :login => 'one',
+ :password => 'wrong'
+ )
+ assert response = gateway.purchase(@amount, @credit_card, @options)
+ assert_failure response
+ assert_equal 'Website verification failed, wrong websiteID or password', response.message
+ end
+end
+
diff --git a/test/remote/gateways/remote_stripe_test.rb b/test/remote/gateways/remote_stripe_test.rb
index 06c737cd1dc..f82fb5dbf5a 100644
--- a/test/remote/gateways/remote_stripe_test.rb
+++ b/test/remote/gateways/remote_stripe_test.rb
@@ -4,17 +4,18 @@ class RemoteStripeTest < Test::Unit::TestCase
def setup
@gateway = StripeGateway.new(fixtures(:stripe))
+ @currency = fixtures(:stripe)["currency"]
@amount = 100
+ # You may have to update the currency, depending on your tenant
@credit_card = credit_card('4242424242424242')
@declined_card = credit_card('4000')
@new_credit_card = credit_card('5105105105105100')
@options = {
- :currency => 'CAD',
+ :currency => @currency,
:description => 'ActiveMerchant Test Purchase',
- :email => 'wow@example.com',
- :currency => 'CAD'
+ :email => 'wow@example.com'
}
end
@@ -23,17 +24,8 @@ def test_successful_purchase
assert_success response
assert_equal "charge", response.params["object"]
assert response.params["paid"]
- end
-
- def test_purchase_description
- assert response = @gateway.purchase(@amount, @credit_card, { :currency => 'CAD', :description => "TheDescription", :email => "email@example.com" })
- assert_equal "TheDescription", response.params["description"], "Use the description if it's specified."
-
- assert response = @gateway.purchase(@amount, @credit_card, { :currency => 'CAD', :email => "email@example.com" })
- assert_equal "email@example.com", response.params["description"], "Use the email if no description is specified."
-
- assert response = @gateway.purchase(@amount, @credit_card, { :currency => 'CAD' })
- assert_nil response.params["description"], "No description or email specified."
+ assert_equal "ActiveMerchant Test Purchase", response.params["description"]
+ assert_equal "wow@example.com", response.params["metadata"]["email"]
end
def test_unsuccessful_purchase
@@ -46,6 +38,8 @@ def test_authorization_and_capture
assert authorization = @gateway.authorize(@amount, @credit_card, @options)
assert_success authorization
assert !authorization.params["captured"]
+ assert_equal "ActiveMerchant Test Purchase", authorization.params["description"]
+ assert_equal "wow@example.com", authorization.params["metadata"]["email"]
assert capture = @gateway.capture(@amount, authorization.authorization)
assert_success capture
@@ -89,7 +83,7 @@ def test_unsuccessful_refund
end
def test_successful_store
- assert response = @gateway.store(@credit_card, {:currency => 'CAD', :description => "Active Merchant Test Customer", :email => "email@example.com"})
+ assert response = @gateway.store(@credit_card, {:currency => @currency, :description => "Active Merchant Test Customer", :email => "email@example.com"})
assert_success response
assert_equal "customer", response.params["object"]
assert_equal "Active Merchant Test Customer", response.params["description"]
@@ -103,17 +97,29 @@ def test_successful_update
creation = @gateway.store(@credit_card, {:description => "Active Merchant Update Customer"})
assert response = @gateway.update(creation.params['id'], @new_credit_card)
assert_success response
- assert_equal "Active Merchant Update Customer", response.params["description"]
- first_card = response.params["cards"]["data"].first
- assert_equal response.params["default_card"], first_card["id"]
+ customer_response = response.responses.last
+ assert_equal "Active Merchant Update Customer", customer_response.params["description"]
+ first_card = customer_response.params["cards"]["data"].first
+ assert_equal customer_response.params["default_card"], first_card["id"]
assert_equal @new_credit_card.last_digits, first_card["last4"]
end
def test_successful_unstore
creation = @gateway.store(@credit_card, {:description => "Active Merchant Unstore Customer"})
- assert response = @gateway.unstore(creation.params['id'])
+ customer_id = creation.params['id']
+ card_id = creation.params['cards']['data'].first['id']
+
+ # Unstore the card
+ assert response = @gateway.unstore(customer_id, card_id)
assert_success response
- assert_equal true, response.params["deleted"]
+ assert_equal card_id, response.params['id']
+ assert_equal true, response.params['deleted']
+
+ # Unstore the customer
+ assert response = @gateway.unstore(customer_id)
+ assert_success response
+ assert_equal customer_id, response.params['id']
+ assert_equal true, response.params['deleted']
end
def test_successful_recurring
@@ -173,4 +179,11 @@ def test_refund_partial_application_fee
assert refund = @gateway.refund(@amount - 20, response.authorization, { :refund_fee_amount => 10 })
assert_success refund
end
+
+ def test_creditcard_purchase_with_customer
+ assert response = @gateway.purchase(@amount, @credit_card, @options.merge(:customer => '1234'))
+ assert_success response
+ assert_equal "charge", response.params["object"]
+ assert response.params["paid"]
+ end
end
diff --git a/test/remote/gateways/remote_swipe_checkout_test.rb b/test/remote/gateways/remote_swipe_checkout_test.rb
new file mode 100644
index 00000000000..6299a506fd2
--- /dev/null
+++ b/test/remote/gateways/remote_swipe_checkout_test.rb
@@ -0,0 +1,69 @@
+require 'test_helper'
+
+class RemoteSwipeCheckoutTest < Test::Unit::TestCase
+ def setup
+ @gateway = SwipeCheckoutGateway.new(fixtures(:swipe_checkout))
+
+ @amount = 100
+ @accepted_card = credit_card('1234123412341234')
+ @declined_card = credit_card('1111111111111111')
+ @invalid_card = credit_card('1000000000000000')
+ @empty_card = credit_card('')
+
+ @options = {
+ order_id: '1',
+ billing_address: address,
+ description: 'Store Purchase'
+ }
+ end
+
+ def test_successful_purchase
+ assert response = @gateway.purchase(@amount, @accepted_card, @options)
+ assert_success response
+ assert_equal 'Transaction approved', response.message
+ end
+
+ def test_region_switching
+ assert response = @gateway.purchase(@amount, @accepted_card, @options.merge(:region => 'CA'))
+ assert_success response
+ assert_equal 'Transaction approved', response.message
+ end
+
+ def test_unsuccessful_purchase
+ assert response = @gateway.purchase(@amount, @declined_card, @options)
+ assert_failure response
+ assert_equal 'Transaction declined', response.message
+ end
+
+ def test_invalid_login
+ gateway = SwipeCheckoutGateway.new(
+ login: 'invalid',
+ api_key: 'invalid',
+ region: 'NZ'
+ )
+ assert response = gateway.purchase(@amount, @accepted_card, @options)
+ assert_failure response
+ assert_equal 'Access Denied', response.message
+ end
+
+ def test_invalid_card
+ # Note: Swipe Checkout transaction API returns declined if the card number
+ # is invalid, and "invalid card data" if the card number is empty
+ assert response = @gateway.purchase(@amount, @invalid_card, @options)
+ assert_failure response
+ assert_equal 'Transaction declined', response.message
+ assert_equal 200, response.params['response_code']
+ end
+
+ def test_empty_card
+ assert response = @gateway.purchase(@amount, @empty_card, @options)
+ assert_failure response
+ assert_equal 'Invalid card data', response.message
+ assert_equal 303, response.params['response_code']
+ end
+
+ def test_no_options
+ assert response = @gateway.purchase(@amount, @accepted_card, {})
+ assert_success response
+ end
+end
diff --git a/test/remote/gateways/remote_usa_epay_advanced_test.rb b/test/remote/gateways/remote_usa_epay_advanced_test.rb
index 440c9a350c3..2488438a814 100644
--- a/test/remote/gateways/remote_usa_epay_advanced_test.rb
+++ b/test/remote/gateways/remote_usa_epay_advanced_test.rb
@@ -2,24 +2,15 @@
require 'logger'
class RemoteUsaEpayAdvancedTest < Test::Unit::TestCase
-
def setup
- # Optional Logger Setup
- # UsaEpayAdvancedGateway.logger = Logger.new('/tmp/usa_epay.log')
- # UsaEpayAdvancedGateway.logger.level = Logger::DEBUG
-
- # Optional Wiredump Setup
- # UsaEpayAdvancedGateway.wiredump_device = File.open('/tmp/usa_epay_dump.log', 'a+')
- # UsaEpayAdvancedGateway.wiredump_device.sync = true
-
@gateway = UsaEpayAdvancedGateway.new(fixtures(:usa_epay_advanced))
@amount = 2111
-
+
@credit_card = ActiveMerchant::Billing::CreditCard.new(
:number => '4000100011112224',
- :month => 12,
- :year => 12,
+ :month => 9,
+ :year => 14,
:brand => 'visa',
:verification_value => '123',
:first_name => "Fred",
@@ -28,8 +19,8 @@ def setup
@bad_credit_card = ActiveMerchant::Billing::CreditCard.new(
:number => '4000300011112220',
- :month => 12,
- :year => 12,
+ :month => 9,
+ :year => 14,
:brand => 'visa',
:verification_value => '999',
:first_name => "Fred",
@@ -37,19 +28,19 @@ def setup
)
@check = ActiveMerchant::Billing::Check.new(
- :number => '123456789',
+ :account_number => '123456789',
:routing_number => '120450780',
:account_type => 'checking',
:first_name => "Fred",
:last_name => "Flintstone"
)
-
+
cc_method = [
- {:name => "My CC", :sort => 5, :method => @credit_card},
+ {:name => "My CC", :sort => 5, :method => @credit_card},
{:name => "Other CC", :sort => 12, :method => @credit_card}
]
- @options = {
+ @options = {
:client_ip => '127.0.0.1',
:billing_address => address,
}
@@ -86,6 +77,12 @@ def setup
:amount => 10000
}
+ @run_transaction_check_options = {
+ :payment_method => @check,
+ :command => 'check',
+ :amount => 10000
+ }
+
@run_sale_options = {
:payment_method => @credit_card,
:amount => 5000
@@ -97,12 +94,12 @@ def setup
}
payment_methods = [
- {
+ {
:name => "My Visa", # optional
:sort => 2, # optional
:method => @credit_card
},
- {
+ {
:name => "My Checking",
:method => @check
}
@@ -110,7 +107,7 @@ def setup
end
# Standard Gateway ==================================================
-
+
def test_purchase
assert response = @gateway.purchase(@amount, @credit_card, @options)
assert_equal 'A', response.params['run_sale_return']['result_code']
@@ -130,7 +127,7 @@ def test_capture
def test_void
assert purchase = @gateway.purchase(@amount, @credit_card, @options.dup)
-
+
assert credit = @gateway.void(purchase.authorization, @options)
assert_equal 'true', credit.params['void_transaction_return']
end
@@ -161,7 +158,7 @@ def test_invalid_login
assert_failure response
assert_equal 'Invalid software ID', response.message
end
-
+
# Customer ==========================================================
def test_add_customer
@@ -172,7 +169,7 @@ def test_add_customer
def test_update_customer
response = @gateway.add_customer(@options.merge(@customer_options))
customer_number = response.params['add_customer_return']
-
+
@options.merge!(@update_customer_options.merge!(:customer_number => customer_number))
response = @gateway.update_customer(@options)
assert response.params['update_customer_return']
@@ -192,7 +189,7 @@ def test_enable_disable_customer
def test_add_customer_payment_method
response = @gateway.add_customer(@options.merge(@customer_options))
customer_number = response.params['add_customer_return']
-
+
@options.merge!(:customer_number => customer_number).merge!(@add_payment_options)
response = @gateway.add_customer_payment_method(@options)
assert response.params['add_customer_payment_method_return']
@@ -201,7 +198,7 @@ def test_add_customer_payment_method
def test_add_customer_payment_method_verify
response = @gateway.add_customer(@options.merge(@customer_options))
customer_number = response.params['add_customer_return']
-
+
@add_payment_options[:payment_method][:method] = @bad_credit_card
@options.merge!(:customer_number => customer_number, :verify => true).merge!(@add_payment_options)
response = @gateway.add_customer_payment_method(@options)
@@ -211,7 +208,7 @@ def test_add_customer_payment_method_verify
def test_get_customer_payment_methods
response = @gateway.add_customer(@options.merge(@customer_options))
customer_number = response.params['add_customer_return']
-
+
response = @gateway.get_customer_payment_methods(:customer_number => customer_number)
assert response.params['get_customer_payment_methods_return']['item']
end
@@ -230,13 +227,14 @@ def test_get_customer_payment_method
def test_update_customer_payment_method
response = @gateway.add_customer(@options.merge(@customer_options))
customer_number = response.params['add_customer_return']
-
+
@options.merge!(:customer_number => customer_number).merge!(@add_payment_options)
response = @gateway.add_customer_payment_method(@options)
payment_method_id = response.params['add_customer_payment_method_return']
- update_payment_options = @add_payment_options[:payment_method].merge(:method_id => payment_method_id,
+ update_payment_options = @add_payment_options[:payment_method].merge(:method_id => payment_method_id,
:name => "Updated Card.")
+
response = @gateway.update_customer_payment_method(update_payment_options)
assert response.params['update_customer_payment_method_return']
end
@@ -244,7 +242,7 @@ def test_update_customer_payment_method
def test_delete_customer_payment_method
response = @gateway.add_customer(@options.merge(@customer_options))
customer_number = response.params['add_customer_return']
-
+
@options.merge!(:customer_number => customer_number).merge!(@add_payment_options)
response = @gateway.add_customer_payment_method(@options)
id = response.params['add_customer_payment_method_return']
@@ -256,7 +254,7 @@ def test_delete_customer_payment_method
def test_delete_customer
response = @gateway.add_customer(@options.merge(@customer_options))
customer_number = response.params['add_customer_return']
-
+
response = @gateway.delete_customer(:customer_number => customer_number)
assert response.params['delete_customer_return']
end
@@ -276,6 +274,14 @@ def test_run_transaction
@options.merge!(@run_transaction_options)
response = @gateway.run_transaction(@options)
assert response.params['run_transaction_return']
+ assert response.success?
+ end
+
+ def test_run_transaction_check
+ @options.merge!(@run_transaction_check_options)
+ response = @gateway.run_transaction(@options)
+ assert response.params['run_transaction_return']
+ assert response.success?
end
def test_run_sale
@@ -345,7 +351,7 @@ def test_refund_transaction
assert response.params['refund_transaction_return']
end
- # TODO how to test override_transction
+ # TODO how to test override_transaction
def test_override_transaction
options = @options.merge(@run_check_sale_options)
response = @gateway.run_check_sale(options)
@@ -413,9 +419,12 @@ def test_get_transaction_custom
response = @gateway.run_sale(@options.merge(@run_sale_options))
reference_number = response.params['run_sale_return']['ref_num']
- response = @gateway.get_transaction_custom(:reference_number => reference_number,
+ response = @gateway.get_transaction_custom(:reference_number => reference_number,
:fields => ['Response.StatusCode', 'Response.Status'])
assert response.params['get_transaction_custom_return']
+ response = @gateway.get_transaction_custom(:reference_number => reference_number,
+ :fields => ['Response.StatusCode'])
+ assert response.params['get_transaction_custom_return']
end
def test_get_check_trace
diff --git a/test/remote/gateways/remote_webpay_test.rb b/test/remote/gateways/remote_webpay_test.rb
index 3aa0edf27ea..27645565d6a 100644
--- a/test/remote/gateways/remote_webpay_test.rb
+++ b/test/remote/gateways/remote_webpay_test.rb
@@ -48,6 +48,24 @@ def test_unsuccessful_purchase
assert_equal 'Your card number is incorrect', response.message
end
+ def test_authorization_and_capture
+ assert authorization = @gateway.authorize(@amount, @credit_card, @options)
+ assert_success authorization
+ assert !authorization.params["captured"]
+
+ assert capture = @gateway.capture(@amount, authorization.authorization)
+ assert_success capture
+ end
+
+ def test_authorization_and_void
+ assert authorization = @gateway.authorize(@amount, @credit_card, @options)
+ assert_success authorization
+ assert !authorization.params["captured"]
+
+ assert void = @gateway.void(authorization.authorization)
+ assert_success void
+ end
+
def test_successful_void
assert response = @gateway.purchase(@amount, @credit_card, @options)
assert_success response
diff --git a/test/remote/gateways/remote_wirecard_test.rb b/test/remote/gateways/remote_wirecard_test.rb
index 0499974350e..34f715f053f 100644
--- a/test/remote/gateways/remote_wirecard_test.rb
+++ b/test/remote/gateways/remote_wirecard_test.rb
@@ -43,7 +43,7 @@ def test_successful_authorize_and_capture
amount = @amount
assert auth = @gateway.authorize(amount, @credit_card, @options)
assert_success auth
- assert auth.message[/THIS IS A DEMO/]
+ assert_match /THIS IS A DEMO/, auth.message
assert auth.authorization
assert capture = @gateway.capture(amount, auth.authorization, @options)
assert_success capture
@@ -52,7 +52,7 @@ def test_successful_authorize_and_capture
def test_successful_authorize_and_partial_capture
assert auth = @gateway.authorize(@amount, @credit_card, @options)
assert_success auth
- assert auth.message[/THIS IS A DEMO/]
+ assert_match /THIS IS A DEMO/, auth.message
assert auth.authorization
#Capture some of the authorized amount
@@ -60,11 +60,30 @@ def test_successful_authorize_and_partial_capture
assert_success capture
end
+ def test_successful_void
+ assert response = @gateway.authorize(@amount, @credit_card, @options)
+ assert_success response
+ assert response.authorization
+
+ assert void = @gateway.void(response.authorization)
+ assert_success void
+ assert_match /THIS IS A DEMO/, void.message
+ end
+
+ def test_successful_refund
+ assert response = @gateway.purchase(@amount, @credit_card, @options)
+ assert_success response
+ assert response.authorization
+
+ assert refund = @gateway.refund(@amount - 20, response.authorization)
+ assert_success refund
+ assert_match /THIS IS A DEMO/, refund.message
+ end
+
def test_successful_purchase
assert response = @gateway.purchase(@amount, @credit_card, @options)
- # puts response.message
assert_success response
- assert response.message[/THIS IS A DEMO/]
+ assert_match /THIS IS A DEMO/, response.message
end
def test_successful_purchase_with_german_address_german_state_and_german_phone
@@ -110,6 +129,18 @@ def test_unauthorized_capture
assert_equal "Could not find referenced transaction for GuWID 1234567890123456789012.", response.message
end
+ def test_failed_refund
+ assert refund = @gateway.refund(@amount - 20, 'C428094138244444404448')
+ assert_failure refund
+ assert_match /Could not find referenced transaction/, refund.message
+ end
+
+ def test_failed_void
+ assert void = @gateway.void('C428094138244444404448')
+ assert_failure void
+ assert_match /Could not find referenced transaction/, void.message
+ end
+
def test_invalid_login
gateway = WirecardGateway.new(:login => '', :password => '', :signature => '')
assert response = gateway.purchase(@amount, @credit_card, @options)
diff --git a/test/remote/integrations/remote_payu_in_integration_test.rb b/test/remote/integrations/remote_payu_in_integration_test.rb
index be8aa9c8547..72680842425 100644
--- a/test/remote/integrations/remote_payu_in_integration_test.rb
+++ b/test/remote/integrations/remote_payu_in_integration_test.rb
@@ -4,7 +4,7 @@ class RemotePayuInIntegrationTest < Test::Unit::TestCase
include ActiveMerchant::Billing::Integrations
def setup
- @payu_in = PayuIn::Notification.new(http_raw_data, :credential1 => 'C0Dr8m', :credential2 => '3sf0jURk')
+ @payu_in = PayuIn::Notification.new(http_raw_data, :credential1 => 'merchant_id', :credential2 => 'secret')
end
def test_raw
@@ -21,6 +21,6 @@ def test_raw
private
def http_raw_data
- "mihpayid=403993715508030204&mode=CC&status=success&unmappedstatus=captured&key=C0Dr8m&txnid=4ba4afe87f7e73468f2a&amount=10.00&discount=0.00&addedon=2013-05-10 18 32 30&productinfo=Product Info&firstname=Payu-Admin&lastname=&address1=&address2=&city=&state=&country=&zipcode=&email=test@example.com&phone=1234567890&udf1=&udf2=&udf3=&udf4=&udf5=&udf6=&udf7=&udf8=&udf9=&udf10=&hash=ef0c1b509a42b802a4938c25dc9bb9efe40b75a7dfb8bde1a6f126fa1f86cee264c5e5a17e87db85150d6d8912eafda838416e669712f1989dcb9cbdb8c24219&field1=313069903923&field2=999999&field3=59117331831301&field4=-1&field5=&field6=&field7=&field8=&PG_TYPE=HDFC&bank_ref_num=59117331831301&bankcode=CC&error=E000&cardnum=512345XXXXXX2346&cardhash=766f0227cc4b4c5f773a04cb31d8d1c5be071dd8d08fe365ecf5e2e5c947546d"
+ "mihpayid=403993715508030204&mode=CC&status=success&unmappedstatus=captured&key=merchant_id&txnid=4ba4afe87f7e73468f2a&amount=10.00&discount=0.00&addedon=2013-05-10 18 32 30&productinfo=Product Info&firstname=Payu-Admin&lastname=&address1=&address2=&city=&state=&country=&zipcode=&email=test@example.com&phone=1234567890&udf1=&udf2=&udf3=&udf4=&udf5=&udf6=&udf7=&udf8=&udf9=&udf10=&hash=ef0c1b509a42b802a4938c25dc9bb9efe40b75a7dfb8bde1a6f126fa1f86cee264c5e5a17e87db85150d6d8912eafda838416e669712f1989dcb9cbdb8c24219&field1=313069903923&field2=999999&field3=59117331831301&field4=-1&field5=&field6=&field7=&field8=&PG_TYPE=HDFC&bank_ref_num=59117331831301&bankcode=CC&error=E000&cardnum=512345XXXXXX2346&cardhash=766f0227cc4b4c5f773a04cb31d8d1c5be071dd8d08fe365ecf5e2e5c947546d"
end
end
diff --git a/test/test_helper.rb b/test/test_helper.rb
index 6b37b224c42..7f00a54a75a 100644
--- a/test/test_helper.rb
+++ b/test/test_helper.rb
@@ -94,23 +94,23 @@ def assert_false(boolean, message = nil)
# A handy little assertion to check for a successful response:
#
# # Instead of
- # assert_success response
+ # assert response.success?
#
# # DRY that up with
# assert_success response
#
# A message will automatically show the inspection of the response
# object if things go afoul.
- def assert_success(response)
+ def assert_success(response, message=nil)
clean_backtrace do
- assert response.success?, "Response failed: #{response.inspect}"
+ assert response.success?, build_message(nil, "#{message + "\n" if message}Response expected to succeed: >", response)
end
end
# The negative of +assert_success+
- def assert_failure(response)
+ def assert_failure(response, message=nil)
clean_backtrace do
- assert_false response.success?, "Response expected to fail: #{response.inspect}"
+ assert !response.success?, build_message(nil, "#{message + "\n" if message}Response expected to fail: >", response)
end
end
diff --git a/test/unit/base_test.rb b/test/unit/base_test.rb
index 2ec4f4721ac..5679e4e9816 100644
--- a/test/unit/base_test.rb
+++ b/test/unit/base_test.rb
@@ -18,18 +18,32 @@ def test_should_return_a_new_gateway_specified_by_symbol_name
assert_equal LinkpointGateway, Base.gateway(:linkpoint)
end
- def test_should_raise_when_invalid_gateway_is_passed
- assert_raise NameError do
- Base.gateway(:nil)
+ def test_should_raise_when_nil_gateway_is_passed
+ e = assert_raise ArgumentError do
+ Base.gateway(nil)
end
+ assert_equal 'A gateway provider must be specified', e.message
+ end
- assert_raise NameError do
+ def test_should_raise_when_empty_gateway_is_passed
+ e = assert_raise ArgumentError do
Base.gateway('')
end
+ assert_equal 'A gateway provider must be specified', e.message
+ end
- assert_raise NameError do
+ def test_should_raise_when_invalid_gateway_symbol_is_passed
+ e = assert_raise ArgumentError do
Base.gateway(:hotdog)
end
+ assert_equal 'The specified gateway is not valid (hotdog)', e.message
+ end
+
+ def test_should_raise_when_invalid_gateway_string_is_passed
+ e = assert_raise ArgumentError do
+ Base.gateway('hotdog')
+ end
+ assert_equal 'The specified gateway is not valid (hotdog)', e.message
end
def test_should_return_an_integration_by_name
diff --git a/test/unit/gateways/app55_test.rb b/test/unit/gateways/app55_test.rb
new file mode 100644
index 00000000000..8623a0f6d89
--- /dev/null
+++ b/test/unit/gateways/app55_test.rb
@@ -0,0 +1,51 @@
+require 'test_helper'
+
+class App55Test < Test::Unit::TestCase
+ def setup
+ @gateway = App55Gateway.new(
+ api_key: 'ABC',
+ api_secret: 'DEF'
+ )
+
+ @credit_card = credit_card
+ @amount = 100
+
+ @options = {
+ billing_address: address,
+ description: 'app55 active merchant unit test'
+ }
+ end
+
+ def test_successful_purchase
+ @gateway.expects(:ssl_request).returns(successful_purchase_response)
+
+ assert response = @gateway.purchase(@amount, @credit_card, @options)
+ assert_instance_of Response, response
+ assert_success response
+
+ assert_equal '130703144451_78313', response.authorization
+ assert response.test?
+ end
+
+ def test_unsuccessful_purchase
+ @gateway.expects(:ssl_request).returns(failed_purchase_response)
+
+ assert response = @gateway.purchase(@amount, @credit_card, @options)
+ assert_failure response
+ assert response.test?
+ end
+
+ private
+
+ def successful_purchase_response
+ <<-RESPONSE
+ {"sig":"TxjO6RNAQYstte69KYQu8zmxF_8=","transaction":{"id":"130703144451_78313","description":"app55 active merchant unit test","currency":"GBP","code":"succeeded","amount":"1.00","auth_code":"06603"},"ts":"20130703134451"}
+ RESPONSE
+ end
+
+ def failed_purchase_response
+ <<-RESPONSE
+ {"error":{"message":"Invalid card number supplied.","type":"validation-error","code":197123}}
+ RESPONSE
+ end
+end
diff --git a/test/unit/gateways/authorize_net_test.rb b/test/unit/gateways/authorize_net_test.rb
index db70bb2abfe..61b462bb675 100644
--- a/test/unit/gateways/authorize_net_test.rb
+++ b/test/unit/gateways/authorize_net_test.rb
@@ -101,6 +101,14 @@ def test_failed_authorization
assert_equal '508141794', response.authorization
end
+ def test_failed_already_actioned_capture
+ @gateway.expects(:ssl_post).returns(already_actioned_capture_response)
+
+ assert response = @gateway.capture(50, '123456789')
+ assert_instance_of Response, response
+ assert_failure response
+ end
+
def test_add_address_outsite_north_america
result = {}
@@ -150,6 +158,14 @@ def test_add_duplicate_window_with_duplicate_window
assert_equal 0, result[:duplicate_window]
end
+ def test_add_cardholder_authentication_value
+ result = {}
+ params = {:cardholder_authentication_value => 'E0Mvq8AAABEiMwARIjNEVWZ3iJk=', :authentication_indicator => '2'}
+ @gateway.send(:add_customer_data, result, params)
+ assert_equal 'E0Mvq8AAABEiMwARIjNEVWZ3iJk=', result[:cardholder_authentication_value]
+ assert_equal '2', result[:authentication_indicator]
+ end
+
def test_purchase_is_valid_csv
params = { :amount => '1.01' }
@@ -186,6 +202,13 @@ def test_authorization_code_included_in_params
assert_equal('d1GENk', response.params['authorization_code'] )
end
+ def test_cardholder_authorization_code_included_in_params
+ @gateway.expects(:ssl_post).returns(successful_purchase_response)
+
+ response = @gateway.capture(50, '123456789')
+ assert_equal('2', response.params['cardholder_authentication_code'] )
+ end
+
def test_capture_passing_extra_info
response = stub_comms do
@gateway.capture(50, '123456789', :description => "Yo", :order_id => "Sweetness")
@@ -416,6 +439,10 @@ def failed_authorization_response
'$2$,$1$,$1$,$This transaction was declined.$,$advE7f$,$Y$,$508141794$,$5b3fe66005f3da0ebe51$,$$,$1.00$,$CC$,$auth_only$,$$,$Longbob$,$Longsen$,$$,$$,$$,$$,$$,$$,$$,$$,$$,$$,$$,$$,$$,$$,$$,$$,$$,$$,$$,$$,$$,$$,$2860A297E0FE804BCB9EF8738599645C$,$P$,$2$,$$,$$,$$,$$,$$,$$,$$,$$,$$,$$,$$,$$,$$,$$,$$,$$,$$,$$,$$,$$,$$,$$,$$,$$,$$,$$,$$,$$'
end
+ def already_actioned_capture_response
+ '$1$,$2$,$311$,$This transaction has already been captured.$,$$,$P$,$0$,$$,$$,$1.00$,$CC$,$credit$,$$,$$,$$,$$,$$,$$,$$,$$,$$,$$,$$,$$,$$,$$,$$,$$,$$,$$,$$,$$,$$,$$,$$,$$,$$,$39265D8BA0CDD4F045B5F4129B2AAA01$,$$,$$,$$,$$,$$,$$,$$,$$,$$,$$,$$,$$,$$,$$,$$,$$,$$,$$,$$,$$,$$,$$,$$,$$,$$,$$,$$,$$,$$,$$'
+ end
+
def fraud_review_response
"$4$,$$,$253$,$Thank you! For security reasons your order is currently being reviewed.$,$$,$X$,$0$,$$,$$,$1.00$,$$,$auth_capture$,$$,$$,$$,$$,$$,$$,$$,$$,$$,$$,$$,$$,$$,$$,$$,$$,$$,$$,$$,$$,$$,$$,$$,$$,$$,$207BCBBF78E85CF174C87AE286B472D2$,$M$,$$,$$,$$,$$,$$,$$,$$,$$,$$,$$,$$,$$,$$,$$,$$,$$,$$,$$,$$,$$,$$,$$,$$,$$,$$,$$,$$,$$,$$"
end
diff --git a/test/unit/gateways/balanced_test.rb b/test/unit/gateways/balanced_test.rb
index 174d12998ff..3b4fa9e5226 100644
--- a/test/unit/gateways/balanced_test.rb
+++ b/test/unit/gateways/balanced_test.rb
@@ -283,11 +283,13 @@ def test_store
)
card_uri = '/v1/marketplaces/TEST-MP73SaFdpQePv9dOaG5wXOGO/cards/CC6r6kLUcxW3MxG3AmZoiuTf'
+ account_uri = '/v1/marketplaces/TEST-MP73SaFdpQePv9dOaG5wXOGO/accounts/AC5quPICW5qEHXac1KnjKGYu'
assert response = @gateway.store(@credit_card, {
:email=>'john.buyer@example.org'
})
- assert_instance_of String, response
- assert_equal card_uri, response
+ assert_instance_of Response, response
+ assert_success response
+ assert_equal "#{card_uri};#{account_uri}", response.authorization
end
def test_ensure_does_not_respond_to_credit
diff --git a/test/unit/gateways/bogus_test.rb b/test/unit/gateways/bogus_test.rb
index 87b6148d724..2c2b7798a06 100644
--- a/test/unit/gateways/bogus_test.rb
+++ b/test/unit/gateways/bogus_test.rb
@@ -1,8 +1,10 @@
require 'test_helper'
class BogusTest < Test::Unit::TestCase
- SUCCESS_PLACEHOLDER = '4444333322221111'
- FAILURE_PLACEHOLDER = '4444333311112222'
+ CC_SUCCESS_PLACEHOLDER = '4444333322221111'
+ CC_FAILURE_PLACEHOLDER = '4444333311112222'
+ CHECK_SUCCESS_PLACEHOLDER = '111111111111'
+ CHECK_FAILURE_PLACEHOLDER = '222222222222'
def setup
@gateway = BogusGateway.new(
@@ -10,58 +12,62 @@ def setup
:password => 'bogus'
)
- @creditcard = credit_card(SUCCESS_PLACEHOLDER)
+ @creditcard = credit_card(CC_SUCCESS_PLACEHOLDER)
@response = ActiveMerchant::Billing::Response.new(true, "Transaction successful", :transid => BogusGateway::AUTHORIZATION)
end
def test_authorize
- assert @gateway.authorize(1000, credit_card(SUCCESS_PLACEHOLDER)).success?
- assert !@gateway.authorize(1000, credit_card(FAILURE_PLACEHOLDER)).success?
- assert_raises(ActiveMerchant::Billing::Error) do
+ assert @gateway.authorize(1000, credit_card(CC_SUCCESS_PLACEHOLDER)).success?
+ assert !@gateway.authorize(1000, credit_card(CC_FAILURE_PLACEHOLDER)).success?
+ e = assert_raises(ActiveMerchant::Billing::Error) do
@gateway.authorize(1000, credit_card('123'))
end
+ assert_equal("Bogus Gateway: Use CreditCard number ending in 1 for success, 2 for exception and anything else for error", e.message)
end
def test_purchase
- assert @gateway.purchase(1000, credit_card(SUCCESS_PLACEHOLDER)).success?
- assert !@gateway.purchase(1000, credit_card(FAILURE_PLACEHOLDER)).success?
- assert_raises(ActiveMerchant::Billing::Error) do
+ assert @gateway.purchase(1000, credit_card(CC_SUCCESS_PLACEHOLDER)).success?
+ assert !@gateway.purchase(1000, credit_card(CC_FAILURE_PLACEHOLDER)).success?
+ e = assert_raises(ActiveMerchant::Billing::Error) do
@gateway.purchase(1000, credit_card('123'))
end
+ assert_equal("Bogus Gateway: Use CreditCard number ending in 1 for success, 2 for exception and anything else for error", e.message)
end
def test_recurring
- assert @gateway.recurring(1000, credit_card(SUCCESS_PLACEHOLDER)).success?
- assert !@gateway.recurring(1000, credit_card(FAILURE_PLACEHOLDER)).success?
- assert_raises(ActiveMerchant::Billing::Error) do
+ assert @gateway.recurring(1000, credit_card(CC_SUCCESS_PLACEHOLDER)).success?
+ assert !@gateway.recurring(1000, credit_card(CC_FAILURE_PLACEHOLDER)).success?
+ e = assert_raises(ActiveMerchant::Billing::Error) do
@gateway.recurring(1000, credit_card('123'))
end
+ assert_equal("Bogus Gateway: Use CreditCard number ending in 1 for success, 2 for exception and anything else for error", e.message)
end
def test_capture
assert @gateway.capture(1000, '1337').success?
assert @gateway.capture(1000, @response.params["transid"]).success?
- assert !@gateway.capture(1000, FAILURE_PLACEHOLDER).success?
+ assert !@gateway.capture(1000, CC_FAILURE_PLACEHOLDER).success?
assert_raises(ActiveMerchant::Billing::Error) do
- @gateway.capture(1000, SUCCESS_PLACEHOLDER)
+ @gateway.capture(1000, CC_SUCCESS_PLACEHOLDER)
end
end
def test_credit
- assert @gateway.credit(1000, credit_card(SUCCESS_PLACEHOLDER)).success?
- assert !@gateway.credit(1000, credit_card(FAILURE_PLACEHOLDER)).success?
- assert_raises(ActiveMerchant::Billing::Error) do
+ assert @gateway.credit(1000, credit_card(CC_SUCCESS_PLACEHOLDER)).success?
+ assert !@gateway.credit(1000, credit_card(CC_FAILURE_PLACEHOLDER)).success?
+ e = assert_raises(ActiveMerchant::Billing::Error) do
@gateway.credit(1000, credit_card('123'))
end
+ assert_equal("Bogus Gateway: Use CreditCard number ending in 1 for success, 2 for exception and anything else for error", e.message)
end
def test_refund
assert @gateway.refund(1000, '1337').success?
assert @gateway.refund(1000, @response.params["transid"]).success?
- assert !@gateway.refund(1000, FAILURE_PLACEHOLDER).success?
+ assert !@gateway.refund(1000, CC_FAILURE_PLACEHOLDER).success?
assert_raises(ActiveMerchant::Billing::Error) do
- @gateway.refund(1000, SUCCESS_PLACEHOLDER)
+ @gateway.refund(1000, CC_SUCCESS_PLACEHOLDER)
end
end
@@ -76,18 +82,23 @@ def test_credit_uses_refund
def test_void
assert @gateway.void('1337').success?
assert @gateway.void(@response.params["transid"]).success?
- assert !@gateway.void(FAILURE_PLACEHOLDER).success?
+ assert !@gateway.void(CC_FAILURE_PLACEHOLDER).success?
assert_raises(ActiveMerchant::Billing::Error) do
- @gateway.void(SUCCESS_PLACEHOLDER)
+ @gateway.void(CC_SUCCESS_PLACEHOLDER)
end
end
def test_store
- @gateway.store(@creditcard)
+ assert @gateway.store(credit_card(CC_SUCCESS_PLACEHOLDER)).success?
+ assert !@gateway.store(credit_card(CC_FAILURE_PLACEHOLDER)).success?
+ e = assert_raises(ActiveMerchant::Billing::Error) do
+ @gateway.store(credit_card('123'))
+ end
+ assert_equal("Bogus Gateway: Use CreditCard number ending in 1 for success, 2 for exception and anything else for error", e.message)
end
def test_unstore
- @gateway.unstore(SUCCESS_PLACEHOLDER)
+ @gateway.unstore(CC_SUCCESS_PLACEHOLDER)
end
def test_store_then_purchase
@@ -102,4 +113,58 @@ def test_supported_countries
def test_supported_card_types
assert_equal [:bogus], BogusGateway.supported_cardtypes
end
+
+ def test_authorize_with_check
+ assert @gateway.authorize(1000, check(:account_number => CHECK_SUCCESS_PLACEHOLDER, :number => nil)).success?
+ assert !@gateway.authorize(1000, check(:account_number => CHECK_FAILURE_PLACEHOLDER, :number => nil)).success?
+ e = assert_raises(ActiveMerchant::Billing::Error) do
+ @gateway.authorize(1000, check(:account_number => '123', :number => nil))
+ end
+ assert_equal("Bogus Gateway: Use bank account number ending in 1 for success, 2 for exception and anything else for error", e.message)
+ end
+
+ def test_purchase_with_check
+ # use account number if number isn't given
+ assert @gateway.purchase(1000, check(:account_number => CHECK_SUCCESS_PLACEHOLDER, :number => nil)).success?
+ assert !@gateway.purchase(1000, check(:account_number => CHECK_FAILURE_PLACEHOLDER, :number => nil)).success?
+ # give priority to number over account_number if given
+ assert !@gateway.purchase(1000, check(:account_number => CHECK_SUCCESS_PLACEHOLDER, :number => CHECK_FAILURE_PLACEHOLDER)).success?
+ assert @gateway.purchase(1000, check(:account_number => CHECK_FAILURE_PLACEHOLDER, :number => CHECK_SUCCESS_PLACEHOLDER)).success?
+ e = assert_raises(ActiveMerchant::Billing::Error) do
+ @gateway.purchase(1000, check(:account_number => '123', :number => nil))
+ end
+ assert_equal("Bogus Gateway: Use bank account number ending in 1 for success, 2 for exception and anything else for error", e.message)
+ end
+
+ def test_recurring_with_check
+ assert @gateway.recurring(1000, check(:account_number => CHECK_SUCCESS_PLACEHOLDER, :number => nil)).success?
+ assert !@gateway.recurring(1000, check(:account_number => CHECK_FAILURE_PLACEHOLDER, :number => nil)).success?
+ e = assert_raises(ActiveMerchant::Billing::Error) do
+ @gateway.recurring(1000, check(:account_number => '123', :number => nil))
+ end
+ assert_equal("Bogus Gateway: Use bank account number ending in 1 for success, 2 for exception and anything else for error", e.message)
+ end
+
+ def test_store_with_check
+ assert @gateway.store(check(:account_number => CHECK_SUCCESS_PLACEHOLDER, :number => nil)).success?
+ assert !@gateway.store(check(:account_number => CHECK_FAILURE_PLACEHOLDER, :number => nil)).success?
+ e = assert_raises(ActiveMerchant::Billing::Error) do
+ @gateway.store(check(:account_number => '123', :number => nil))
+ end
+ assert_equal("Bogus Gateway: Use bank account number ending in 1 for success, 2 for exception and anything else for error", e.message)
+ end
+
+ def test_credit_with_check
+ assert @gateway.credit(1000, check(:account_number => CHECK_SUCCESS_PLACEHOLDER, :number => nil)).success?
+ assert !@gateway.credit(1000, check(:account_number => CHECK_FAILURE_PLACEHOLDER, :number => nil)).success?
+ e = assert_raises(ActiveMerchant::Billing::Error) do
+ @gateway.credit(1000, check(:account_number => '123', :number => nil))
+ end
+ assert_equal("Bogus Gateway: Use bank account number ending in 1 for success, 2 for exception and anything else for error", e.message)
+ end
+
+ def test_store_then_purchase_with_check
+ reference = @gateway.store(check(:account_number => CHECK_SUCCESS_PLACEHOLDER, :number => nil))
+ assert @gateway.purchase(1000, reference.authorization).success?
+ end
end
diff --git a/test/unit/gateways/braintree_blue_test.rb b/test/unit/gateways/braintree_blue_test.rb
index ff3ae73d0fb..9dc6725d5e3 100644
--- a/test/unit/gateways/braintree_blue_test.rb
+++ b/test/unit/gateways/braintree_blue_test.rb
@@ -87,8 +87,8 @@ def test_merchant_account_id_absent_if_not_provided
end
def test_store_with_verify_card_true
- customer = mock(
- :credit_cards => [],
+ customer = stub(
+ :credit_cards => [stub_everything],
:email => 'email',
:first_name => 'John',
:last_name => 'Smith'
@@ -106,9 +106,45 @@ def test_store_with_verify_card_true
assert_equal response.params["customer_vault_id"], response.authorization
end
+ def test_passes_email
+ customer = stub(
+ :credit_cards => [stub_everything],
+ :email => "bob@example.com",
+ :first_name => 'John',
+ :last_name => 'Smith',
+ id: "123"
+ )
+ result = Braintree::SuccessfulResult.new(:customer => customer)
+ Braintree::CustomerGateway.any_instance.expects(:create).with do |params|
+ assert_equal "bob@example.com", params[:email]
+ params
+ end.returns(result)
+
+ response = @gateway.store(credit_card("41111111111111111111"), :email => "bob@example.com")
+ assert_success response
+ end
+
+ def test_scrubs_invalid_email
+ customer = stub(
+ :credit_cards => [stub_everything],
+ :email => nil,
+ :first_name => 'John',
+ :last_name => 'Smith',
+ :id => "123"
+ )
+ result = Braintree::SuccessfulResult.new(:customer => customer)
+ Braintree::CustomerGateway.any_instance.expects(:create).with do |params|
+ assert_equal nil, params[:email]
+ params
+ end.returns(result)
+
+ response = @gateway.store(credit_card("41111111111111111111"), :email => "bogus")
+ assert_success response
+ end
+
def test_store_with_verify_card_false
- customer = mock(
- :credit_cards => [],
+ customer = stub(
+ :credit_cards => [stub_everything],
:email => 'email',
:first_name => 'John',
:last_name => 'Smith'
@@ -128,7 +164,7 @@ def test_store_with_verify_card_false
def test_store_with_billing_address_options
customer_attributes = {
- :credit_cards => [],
+ :credit_cards => [stub_everything],
:email => 'email',
:first_name => 'John',
:last_name => 'Smith'
@@ -141,7 +177,7 @@ def test_store_with_billing_address_options
:zip => "60622",
:country_name => "US"
}
- customer = mock(customer_attributes)
+ customer = stub(customer_attributes)
customer.stubs(:id).returns('123')
result = Braintree::SuccessfulResult.new(:customer => customer)
Braintree::CustomerGateway.any_instance.expects(:create).with do |params|
@@ -155,6 +191,73 @@ def test_store_with_billing_address_options
@gateway.store(credit_card("41111111111111111111"), :billing_address => billing_address)
end
+ def test_store_with_credit_card_token
+ customer = stub(
+ :email => 'email',
+ :first_name => 'John',
+ :last_name => 'Smith'
+ )
+ customer.stubs(:id).returns('123')
+
+ braintree_credit_card = stub_everything(token: "cctoken")
+ customer.stubs(:credit_cards).returns([braintree_credit_card])
+
+ result = Braintree::SuccessfulResult.new(:customer => customer)
+ Braintree::CustomerGateway.any_instance.expects(:create).with do |params|
+ assert_equal "cctoken", params[:credit_card][:token]
+ params
+ end.returns(result)
+
+ response = @gateway.store(credit_card("41111111111111111111"), :credit_card_token => "cctoken")
+ assert_success response
+ assert_equal "cctoken", response.params["braintree_customer"]["credit_cards"][0]["token"]
+ assert_equal "cctoken", response.params["credit_card_token"]
+ end
+
+ def test_store_with_customer_id
+ customer = stub(
+ :email => 'email',
+ :first_name => 'John',
+ :last_name => 'Smith',
+ :credit_cards => [stub_everything]
+ )
+ customer.stubs(:id).returns("customerid")
+
+ result = Braintree::SuccessfulResult.new(:customer => customer)
+ Braintree::CustomerGateway.any_instance.expects(:find).
+ with("customerid").
+ raises(Braintree::NotFoundError)
+ Braintree::CustomerGateway.any_instance.expects(:create).with do |params|
+ assert_equal "customerid", params[:id]
+ params
+ end.returns(result)
+
+ response = @gateway.store(credit_card("41111111111111111111"), :customer => "customerid")
+ assert_success response
+ assert_equal "customerid", response.params["braintree_customer"]["id"]
+ end
+
+ def test_store_with_existing_customer_id
+ credit_card = stub(
+ customer_id: "customerid",
+ token: "cctoken"
+ )
+
+ result = Braintree::SuccessfulResult.new(credit_card: credit_card)
+ Braintree::CustomerGateway.any_instance.expects(:find).with("customerid")
+ Braintree::CreditCardGateway.any_instance.expects(:create).with do |params|
+ assert_equal "customerid", params[:customer_id]
+ assert_equal "41111111111111111111", params[:number]
+ params
+ end.returns(result)
+
+ response = @gateway.store(credit_card("41111111111111111111"), customer: "customerid")
+ assert_success response
+ assert_nil response.params["braintree_customer"]
+ assert_equal "customerid", response.params["customer_vault_id"]
+ assert_equal "cctoken", response.params["credit_card_token"]
+ end
+
def test_update_with_cvv
stored_credit_card = mock(:token => "token", :default? => true)
customer = mock(:credit_cards => [stored_credit_card], :id => '123')
@@ -171,8 +274,8 @@ def test_update_with_cvv
end
def test_update_with_verify_card_true
- stored_credit_card = mock(:token => "token", :default? => true)
- customer = mock(:credit_cards => [stored_credit_card], :id => '123')
+ stored_credit_card = stub(:token => "token", :default? => true)
+ customer = stub(:credit_cards => [stored_credit_card], :id => '123')
Braintree::CustomerGateway.any_instance.stubs(:find).with('vault_id').returns(customer)
BraintreeBlueGateway.any_instance.stubs(:customer_hash)
@@ -268,6 +371,18 @@ def test_address_country_handling
@gateway.purchase(100, credit_card("41111111111111111111"), :billing_address => {:country_code_numeric => 840})
end
+ def test_address_zip_handling
+ Braintree::TransactionGateway.any_instance.expects(:sale).with do |params|
+ (params[:billing][:postal_code] == "12345")
+ end.returns(braintree_result)
+ @gateway.purchase(100, credit_card("41111111111111111111"), :billing_address => {:zip => "12345"})
+
+ Braintree::TransactionGateway.any_instance.expects(:sale).with do |params|
+ (params[:billing][:postal_code] == nil)
+ end.returns(braintree_result)
+ @gateway.purchase(100, credit_card("41111111111111111111"), :billing_address => {:zip => "1234567890"})
+ end
+
def test_passes_recurring_flag
@gateway = BraintreeBlueGateway.new(
:merchant_id => 'test',
@@ -305,7 +420,7 @@ def test_default_logger_sets_warn_level_without_overwriting_global
assert Braintree::Configuration.logger.level != Logger::DEBUG
Braintree::Configuration.logger.level = Logger::DEBUG
- # Re-instatiate a gateway to show it doesn't touch the global
+ # Re-instantiate a gateway to show it doesn't touch the global
gateway = BraintreeBlueGateway.new(
:merchant_id => 'test',
:public_key => 'test',
diff --git a/test/unit/gateways/conekta_test.rb b/test/unit/gateways/conekta_test.rb
new file mode 100644
index 00000000000..753a466edf0
--- /dev/null
+++ b/test/unit/gateways/conekta_test.rb
@@ -0,0 +1,280 @@
+require 'test_helper'
+
+class ConektaTest < Test::Unit::TestCase
+ def setup
+ @gateway = ConektaGateway.new(:key => "1tv5yJp3xnVZ7eK67m4h")
+
+ @amount = 300
+
+ @credit_card = ActiveMerchant::Billing::CreditCard.new(
+ :number => "4111111111111111",
+ :verification_value => "183",
+ :month => "01",
+ :year => "2018",
+ :first_name => "Mario F.",
+ :last_name => "Moreno Reyes"
+ )
+
+ @declined_card = ActiveMerchant::Billing::CreditCard.new(
+ :number => "4000000000000002",
+ :verification_value => "183",
+ :month => "01",
+ :year => "2018",
+ :first_name => "Mario F.",
+ :last_name => "Moreno Reyes"
+ )
+
+ @options = {
+ :description => 'Blue clip',
+ :success_url => "https://www.example.com/success",
+ :failure_url => "https://www.example.com/failure",
+ :address1 => "Rio Missisipi #123",
+ :address2 => "Paris",
+ :city => "Guerrero",
+ :country => "Mexico",
+ :zip => "5555",
+ :name => "Mario Reyes",
+ :phone => "12345678",
+ :carrier => "Estafeta"
+ }
+ end
+
+ def test_successful_tokenized_purchase
+ @gateway.expects(:ssl_request).returns(successful_purchase_response)
+ assert response = @gateway.purchase(@amount, 'tok_xxxxxxxxxxxxxxxx', @options)
+ assert_instance_of Response, response
+ assert_success response
+ assert_equal nil, response.message
+ assert response.test?
+ end
+
+ def test_successful_purchase
+ @gateway.expects(:ssl_request).returns(successful_purchase_response)
+ assert response = @gateway.purchase(@amount, @credit_card, @options)
+ assert_instance_of Response, response
+ assert_success response
+ assert_equal nil, response.message
+ assert response.test?
+ end
+
+ def test_unsuccessful_purchase
+ @gateway.expects(:ssl_request).returns(failed_purchase_response)
+ assert response = @gateway.purchase(@amount, @declined_card, @options)
+ assert_failure response
+ assert response.test?
+ end
+
+ def test_unsuccessful_refund
+ @gateway.expects(:ssl_request).returns(failed_refund_response)
+ assert response = @gateway.refund("1", @amount, @options)
+ assert_failure response
+ assert response.test?
+ end
+
+ def test_successful_authorize
+ @gateway.expects(:ssl_request).returns(successful_authorize_response)
+ assert response = @gateway.authorize(@amount, @credit_card, @options)
+ assert_success response
+ assert_instance_of Response, response
+ assert_equal nil, response.message
+ assert response.test?
+ end
+
+ def test_unsuccessful_authorize
+ @gateway.expects(:ssl_request).returns(failed_authorize_response)
+ assert response = @gateway.authorize(@amount, @declined_card, @options)
+ assert_failure response
+ assert response.test?
+ end
+
+ def test_unsuccessful_capture
+ @gateway.expects(:ssl_request).returns(failed_purchase_response)
+ assert response = @gateway.capture("1", @amount, @options)
+ assert_failure response
+ assert response.test?
+ end
+
+ def test_invalid_login
+ gateway = ConektaGateway.new(:key => 'invalid_token')
+ gateway.expects(:ssl_request).returns(failed_login_response)
+ assert response = gateway.purchase(@amount, @credit_card, @options)
+ assert_failure response
+ assert response.test?
+ end
+
+ private
+
+ def successful_purchase_response
+ {
+ 'id' => '521b859fcfc26c0f180002d9',
+ 'livemode' => false,
+ 'created_at' => 1377535391,
+ 'status' => 'pre_authorized',
+ 'currency' => 'MXN',
+ 'description' => 'Blue clip',
+ 'reference_id' => nil,
+ 'failure_code' => nil,
+ 'failure_message' => nil,
+ 'object' => 'charge',
+ 'amount' => 300,
+ 'processed_at' => nil,
+ 'fee' => 348,
+ 'card' => {
+ 'name' => 'Mario Reyes',
+ 'exp_month' => '01',
+ 'exp_year' => '18',
+ 'street2' => 'Paris',
+ 'street3' => 'nil',
+ 'city' => 'Guerrero',
+ 'zip' => '5555',
+ 'country' => 'Mexico',
+ 'brand' => 'VISA',
+ 'last4' => '1111',
+ 'object' => 'card',
+ 'fraud_response' => '3d_secure_required',
+ 'redirect_form' => {
+ 'url' => 'https => //eps.banorte.com/secure3d/Solucion3DSecure.htm',
+ 'action' => 'POST',
+ 'attributes' => {
+ 'MerchantId' => '7376961',
+ 'MerchantName' => 'GRUPO CONEKTAME',
+ 'MerchantCity' => 'EstadodeMexico',
+ 'Cert3D' => '03',
+ 'ClientId' => '60518',
+ 'Name' => '7376962',
+ 'Password' => 'fgt563j',
+ 'TransType' => 'PreAuth',
+ 'Mode' => 'Y',
+ 'E1' => 'qKNKjndV9emCxuKE1G4z',
+ 'E2' => '521b859fcfc26c0f180002d9',
+ 'E3' => 'Y',
+ 'ResponsePath' => 'https => //eps.banorte.com/RespuestaCC.jsp',
+ 'CardType' => 'VISA',
+ 'Card' => '4111111111111111',
+ 'Cvv2Indicator' => '1',
+ 'Cvv2Val' => '183',
+ 'Expires' => '01/18',
+ 'Total' => '3.0',
+ 'ForwardPath' => 'http => //localhost => 3000/charges/banorte_3d_secure_response',
+ 'auth_token' => 'qKNKjndV9emCxuKE1G4z'
+ }
+ }
+ }
+ }.to_json
+ end
+
+ def failed_purchase_response
+ {
+ 'message' => 'The card was declined',
+ 'type' => 'invalid_parameter_error',
+ 'param' => ''
+ }.to_json
+ end
+
+ def failed_bank_purchase_response
+ {
+ 'message' => 'The minimum purchase is 15 MXN pesos for bank transfer payments',
+ 'type' => 'invalid_parameter_error',
+ 'param' => ''
+ }.to_json
+ end
+
+ def failed_refund_response
+ {
+ 'object' => 'error',
+ 'type' => 200,
+ 'message' => 'The charge does not exist or it is not suitable for this operation'
+ }.to_json
+ end
+
+ def failed_void_response
+ {
+ 'object' => 'error',
+ 'type' => 200,
+ 'message' => 'The charge does not exist or it is not suitable for this operation'
+ }.to_json
+ end
+
+ def successful_authorize_response
+ {
+ 'id' => '521b859fcfc26c0f180002d9',
+ 'livemode' => false,
+ 'created_at' => 1377535391,
+ 'status' => 'pre_authorized',
+ 'currency' => 'MXN',
+ 'description' => 'Blue clip',
+ 'reference_id' => nil,
+ 'failure_code' => nil,
+ 'failure_message' => nil,
+ 'object' => 'charge',
+ 'amount' => 300,
+ 'processed_at' => nil,
+ 'fee' => 348,
+ 'card' => {
+ 'name' => 'Mario Reyes',
+ 'exp_month' => '01',
+ 'exp_year' => '18',
+ 'street2' => 'Paris',
+ 'street3' => 'nil',
+ 'city' => 'Guerrero',
+ 'zip' => '5555',
+ 'country' => 'Mexico',
+ 'brand' => 'VISA',
+ 'last4' => '1111',
+ 'object' => 'card',
+ 'fraud_response' => '3d_secure_required',
+ 'redirect_form' => {
+ 'url' => 'https => //eps.banorte.com/secure3d/Solucion3DSecure.htm',
+ 'action' => 'POST',
+ 'attributes' => {
+ 'MerchantId' => '7376961',
+ 'MerchantName' => 'GRUPO CONEKTAME',
+ 'MerchantCity' => 'EstadodeMexico',
+ 'Cert3D' => '03',
+ 'ClientId' => '60518',
+ 'Name' => '7376962',
+ 'Password' => 'fgt563j',
+ 'TransType' => 'PreAuth',
+ 'Mode' => 'Y',
+ 'E1' => 'qKNKjndV9emCxuKE1G4z',
+ 'E2' => '521b859fcfc26c0f180002d9',
+ 'E3' => 'Y',
+ 'ResponsePath' => 'https => //eps.banorte.com/RespuestaCC.jsp',
+ 'CardType' => 'VISA',
+ 'Card' => '4111111111111111',
+ 'Cvv2Indicator' => '1',
+ 'Cvv2Val' => '183',
+ 'Expires' => '01/18',
+ 'Total' => '3.0',
+ 'ForwardPath' => 'http => //localhost => 3000/charges/banorte_3d_secure_response',
+ 'auth_token' => 'qKNKjndV9emCxuKE1G4z'
+ }
+ }
+ }
+ }.to_json
+ end
+
+ def failed_authorize_response
+ {
+ 'message' => 'The card was declined',
+ 'type' => 'invalid_parameter_error',
+ 'param' => ''
+ }.to_json
+ end
+
+ def failed_capture_response
+ {
+ 'object' => 'error',
+ 'type' => 200,
+ 'message' => 'The charge does not exist or it is not suitable for this operation'
+ }.to_json
+ end
+
+ def failed_login_response
+ {
+ 'object' => 'error',
+ 'type' => 'authentication_error',
+ 'message' => 'Unrecognized authentication token'
+ }.to_json
+ end
+end
diff --git a/test/unit/gateways/elavon_test.rb b/test/unit/gateways/elavon_test.rb
index b4c0054ca23..3ae26fb5c3d 100644
--- a/test/unit/gateways/elavon_test.rb
+++ b/test/unit/gateways/elavon_test.rb
@@ -97,10 +97,6 @@ def test_invalid_login
assert_failure response
end
- def test_supported_countries
- assert_equal ['US', 'CA'], ElavonGateway.supported_countries
- end
-
def test_supported_card_types
assert_equal [:visa, :master, :american_express, :discover], ElavonGateway.supported_cardtypes
end
diff --git a/test/unit/gateways/eway_rapid_test.rb b/test/unit/gateways/eway_rapid_test.rb
index ab8a7eb246a..78063eef570 100644
--- a/test/unit/gateways/eway_rapid_test.rb
+++ b/test/unit/gateways/eway_rapid_test.rb
@@ -13,48 +13,48 @@ def setup
@amount = 100
end
- def test_purchase_calls_sub_methods
- request = sequence("request")
- @gateway.expects(:setup_purchase).with(@amount, {:order_id => 1, :redirect_url => "http://example.com/"}).returns(Response.new(true, "Success", {"formactionurl" => "url"}, :authorization => "auth1")).in_sequence(request)
- @gateway.expects(:run_purchase).with("auth1", @credit_card, "url").returns(Response.new(true, "Success", {}, :authorization => "auth2")).in_sequence(request)
- @gateway.expects(:status).with("auth2").returns(Response.new(true, "Success", {})).in_sequence(request)
+ def test_successful_purchase
+ response = stub_comms do
+ @gateway.purchase(@amount, @credit_card)
+ end.respond_with(successful_purchase_response)
- response = @gateway.purchase(@amount, @credit_card, :order_id => 1)
assert_success response
+ assert_equal "Transaction Approved Successful", response.message
+ assert_equal 10440187, response.authorization
+ assert response.test?
end
- def test_successful_setup_purchase
- response = stub_comms do
- @gateway.setup_purchase(@amount, :redirect_url => "http://bogus")
- end.respond_with(successful_setup_purchase_response)
+ def test_localized_currency
+ stub_comms do
+ @gateway.purchase(100, @credit_card, :currency => 'CAD')
+ end.check_request do |endpoint, data, headers|
+ assert_match '"TotalAmount":"100"', data
+ end.respond_with(successful_purchase_response)
- assert_success response
- assert_equal "Succeeded", response.message
- assert_equal(
- "60CF3xWrFUQeDCEsJcA8zNHaspAT3CKpe-0DiqWjTYA3RZw1xhw2LU-BFCNYbr7eJt8KFaxCxmzYh9WDAYX8yIuYexTq0tC8i2kOt0dm0EV-mjxYEQ2YeHP2dazkSc7j58OiT",
- response.authorization
- )
- assert_equal "https://secure-au.sandbox.ewaypayments.com/Process", response.form_url
- assert response.test?
+ stub_comms do
+ @gateway.purchase(100, @credit_card, :currency => 'JPY')
+ end.check_request do |endpoint, data, headers|
+ assert_match '"TotalAmount":"1"', data
+ end.respond_with(successful_purchase_response)
end
- def test_failed_setup_purchase
+ def test_failed_purchase
response = stub_comms do
- @gateway.setup_purchase(@amount, :redirect_url => "http://bogus")
- end.respond_with(failed_setup_purchase_response)
+ @gateway.purchase(-100, @credit_card)
+ end.respond_with(failed_purchase_response)
assert_failure response
- assert_equal "RedirectURL Required", response.message
+ assert_equal "Invalid Payment TotalAmount", response.message
assert_nil response.authorization
assert response.test?
end
- def test_setup_purchase_with_all_options
+ def test_purchase_with_all_options
response = stub_comms do
- @gateway.setup_purchase(200,
+ @gateway.purchase(200, @credit_card,
+ :transaction_type => 'CustomTransactionType',
:redirect_url => "http://awesomesauce.com",
:ip => "0.0.0.0",
- :request_method => "CustomRequest",
:application_id => "Woohoo",
:description => "Description",
:order_id => "orderid1",
@@ -88,158 +88,161 @@ def test_setup_purchase_with_all_options
}
)
end.check_request do |endpoint, data, headers|
- assert_no_match(%r{#{@credit_card.number}}, data)
-
- assert_match(%r{RedirectUrl>http://awesomesauce.com<}, data)
- assert_match(%r{CustomerIP>0.0.0.0<}, data)
- assert_match(%r{Method>CustomRequest<}, data)
- assert_match(%r{DeviceID>Woohoo<}, data)
-
- assert_match(%r{TotalAmount>200<}, data)
- assert_match(%r{InvoiceDescription>Description<}, data)
- assert_match(%r{InvoiceReference>orderid1<}, data)
- assert_match(%r{CurrencyCode>INR<}, data)
-
- assert_match(%r{Title>Mr.<}, data)
- assert_match(%r{FirstName>Jim<}, data)
- assert_match(%r{LastName>Awesome Smith<}, data)
- assert_match(%r{CompanyName>Awesome Co<}, data)
- assert_match(%r{Street1>1234 My Street<}, data)
- assert_match(%r{Street2>Apt 1<}, data)
- assert_match(%r{City>Ottawa<}, data)
- assert_match(%r{State>ON<}, data)
- assert_match(%r{PostalCode>K1C2N6<}, data)
- assert_match(%r{Country>ca<}, data)
- assert_match(%r{Phone>\(555\)555-5555<}, data)
- assert_match(%r{Fax>\(555\)555-6666<}, data)
- assert_match(%r{Email>jim@example\.com<}, data)
-
- assert_match(%r{Title>Ms.<}, data)
- assert_match(%r{LastName>Baker<}, data)
+ # assert_no_match(%r{#{@credit_card.number}}, data)
+
+ assert_match(%r{"TransactionType":"CustomTransactionType"}, data)
+ assert_match(%r{"RedirectUrl":"http://awesomesauce.com"}, data)
+ assert_match(%r{"CustomerIP":"0.0.0.0"}, data)
+ assert_match(%r{"DeviceID":"Woohoo"}, data)
+
+ assert_match(%r{"TotalAmount":"200"}, data)
+ assert_match(%r{"InvoiceDescription":"Description"}, data)
+ assert_match(%r{"InvoiceReference":"orderid1"}, data)
+ assert_match(%r{"CurrencyCode":"INR"}, data)
+
+ assert_match(%r{"Title":"Mr."}, data)
+ assert_match(%r{"FirstName":"Jim"}, data)
+ assert_match(%r{"LastName":"Awesome Smith"}, data)
+ assert_match(%r{"CompanyName":"Awesome Co"}, data)
+ assert_match(%r{"Street1":"1234 My Street"}, data)
+ assert_match(%r{"Street2":"Apt 1"}, data)
+ assert_match(%r{"City":"Ottawa"}, data)
+ assert_match(%r{"State":"ON"}, data)
+ assert_match(%r{"PostalCode":"K1C2N6"}, data)
+ assert_match(%r{"Country":"ca"}, data)
+ assert_match(%r{"Phone":"\(555\)555-5555"}, data)
+ assert_match(%r{"Fax":"\(555\)555-6666"}, data)
+ assert_match(%r{"Email":"jim@example\.com"}, data)
+
+ assert_match(%r{"Title":"Ms."}, data)
+ assert_match(%r{"LastName":"Baker"}, data)
assert_no_match(%r{Elsewhere Inc.}, data)
- assert_match(%r{Street1>4321 Their St.<}, data)
- assert_match(%r{Street2>Apt 2<}, data)
- assert_match(%r{City>Chicago<}, data)
- assert_match(%r{State>IL<}, data)
- assert_match(%r{PostalCode>60625<}, data)
- assert_match(%r{Country>us<}, data)
- assert_match(%r{Phone>1115555555<}, data)
- assert_match(%r{Fax>1115556666<}, data)
- assert_match(%r{Email>(\s+)?<}, data)
- end.respond_with(successful_setup_purchase_response)
+ assert_match(%r{"Street1":"4321 Their St."}, data)
+ assert_match(%r{"Street2":"Apt 2"}, data)
+ assert_match(%r{"City":"Chicago"}, data)
+ assert_match(%r{"State":"IL"}, data)
+ assert_match(%r{"PostalCode":"60625"}, data)
+ assert_match(%r{"Country":"us"}, data)
+ assert_match(%r{"Phone":"1115555555"}, data)
+ assert_match(%r{"Fax":"1115556666"}, data)
+ assert_match(%r{"Email":null}, data)
+ end.respond_with(successful_purchase_response)
assert_success response
- assert_equal(
- "60CF3xWrFUQeDCEsJcA8zNHaspAT3CKpe-0DiqWjTYA3RZw1xhw2LU-BFCNYbr7eJt8KFaxCxmzYh9WDAYX8yIuYexTq0tC8i2kOt0dm0EV-mjxYEQ2YeHP2dazkSc7j58OiT",
- response.authorization
- )
+ assert_equal 10440187, response.authorization
assert response.test?
end
- def test_successful_run_purchase
- request_sequence = sequence("request")
- @gateway.expects(:ssl_request).returns(successful_setup_purchase_response).in_sequence(request_sequence)
- @gateway.expects(:raw_ssl_request).with(
- :post,
- "https://secure-au.sandbox.ewaypayments.com/Process",
- all_of(
- regexp_matches(%r{EWAY_ACCESSCODE=60CF3xWrFUQeDCEsJcA8zNHaspAT3CKpe-0DiqWjTYA3RZw1xhw2LU-BFCNYbr7eJt8KFaxCxmzYh9WDAYX8yIuYexTq0tC8i2kOt0dm0EV-mjxYEQ2YeHP2dazkSc7j58OiT}),
- regexp_matches(%r{EWAY_CARDNAME=Longbob\+Longsen}),
- regexp_matches(%r{EWAY_CARDNUMBER=#{@credit_card.number}}),
- regexp_matches(%r{EWAY_CARDEXPIRYMONTH=#{@credit_card.month}}),
- regexp_matches(%r{EWAY_CARDEXPIRYYEAR=#{@credit_card.year}}),
- regexp_matches(%r{EWAY_CARDCVN=#{@credit_card.verification_value}})
- ),
- anything
- ).returns(successful_run_purchase_response).in_sequence(request_sequence)
- @gateway.expects(:ssl_request).returns(successful_status_response).in_sequence(request_sequence)
-
- response = @gateway.purchase(@amount, @credit_card, :order_id => 1)
+ def test_successful_store
+ response = stub_comms do
+ @gateway.store(@credit_card, :billing_address => {
+ :title => "Mr.",
+ :name => "Jim Awesome Smith",
+ :company => "Awesome Co",
+ :address1 => "1234 My Street",
+ :address2 => "Apt 1",
+ :city => "Ottawa",
+ :state => "ON",
+ :zip => "K1C2N6",
+ :country => "CA",
+ :phone => "(555)555-5555",
+ :fax => "(555)555-6666"
+ })
+ end.check_request do |endpoint, data, headers|
+ assert_match '"Method":"CreateTokenCustomer"', data
+ end.respond_with(successful_store_response)
+
assert_success response
- assert_equal "Transaction Approved", response.message
- assert_equal(
- "60CF3sfH7-yvAsUAHrdIiGppPrQW7v7DMAXxKkaKwyrIUoqvUvK44XbK9G9HNbngIz_iwQpfmPT_duMgh2G0pXCX8i4z1RAmMHpUQwa6VrghV3Bx9rh_tojjym7LC_fE-eR97",
- response.authorization
- )
+ assert_equal "Transaction Approved Successful", response.message
+ assert_equal 917224224772, response.authorization
assert response.test?
end
- def test_failed_run_purchase
- request_sequence = sequence("request")
- @gateway.expects(:ssl_request).returns(successful_setup_purchase_response).in_sequence(request_sequence)
- @gateway.expects(:raw_ssl_request).returns(failed_run_purchase_response).in_sequence(request_sequence)
+ def test_failed_store
+ response = stub_comms do
+ @gateway.store(@credit_card, :billing_address => {})
+ end.respond_with(failed_store_response)
- response = @gateway.purchase(@amount, @credit_card, :order_id => 1)
assert_failure response
- assert_match %r{Not Found}, response.message
+ assert_equal "Customer CountryCode Required", response.message
assert_nil response.authorization
assert response.test?
end
- def test_successful_status
+ def test_successful_update
response = stub_comms do
- @gateway.status("thetransauth")
+ @gateway.update('faketoken', nil)
end.check_request do |endpoint, data, headers|
- assert_match(%r{thetransauth}, data)
- end.respond_with(successful_status_response)
+ assert_match '"Method":"UpdateTokenCustomer"', data
+ end.respond_with(successful_update_response)
assert_success response
- assert_equal(
- "60CF3sfH7-yvAsUAHrdIiGppPrQW7v7DMAXxKkaKwyrIUoqvUvK44XbK9G9HNbngIz_iwQpfmPT_duMgh2G0pXCX8i4z1RAmMHpUQwa6VrghV3Bx9rh_tojjym7LC_fE-eR97",
- response.authorization
- )
+ assert_equal "Transaction Approved Successful", response.message
+ assert_equal 916161208398, response.authorization
assert response.test?
- assert_equal "Transaction Approved", response.message
- assert_equal "orderid1", response.params["invoicereference"]
end
- def test_failed_status
+ def test_successful_refund
response = stub_comms do
- @gateway.status("thetransauth")
- end.respond_with(failed_status_response)
+ @gateway.refund(@amount, '1234567')
+ end.check_request do |endpoint, data, headers|
+ assert_match /Transaction\/1234567\/Refund$/, endpoint
+ json = JSON.parse(data)
+ assert_equal '100', json['Refund']['TotalAmount']
+ assert_equal '1234567', json['Refund']['TransactionID']
+ end.respond_with(successful_refund_response)
+
+ assert_success response
+ assert_equal "Transaction Approved Successful", response.message
+ assert_equal 10488258, response.authorization
+ assert response.test?
+ end
+
+ def test_failed_refund
+ response = stub_comms do
+ @gateway.refund(@amount, '1234567')
+ end.respond_with(failed_refund_response)
assert_failure response
- assert_equal(
- "A1001WfAHR_QP8daLnG6fQLcadzuCBJbpIp-zsUL6FkQgUyY2MXwVA0etYvflPe_rDBiuOMV-BfTSGDKt7uU3E2bLUhsD1rrXwGT9BTPcOOH_Vh9jHDSn2inqk8udwQIRcxuc",
- response.authorization
- )
+ assert_equal "System Error", response.message
+ assert_nil response.authorization
assert response.test?
- assert_equal "Do Not Honour", response.message
- assert_equal "1", response.params["invoicereference"]
end
- def test_store_calls_sub_methods
- options = {
- :order_id => 1,
- :billing_address => {
- :name => "Jim Awesome Smith",
- }
- }
- @gateway.expects(:purchase).with(0, @credit_card, options.merge(:request_method => "CreateTokenCustomer"))
+ def test_successful_stored_card_purchase
+ response = stub_comms do
+ @gateway.purchase(100, 'the_customer_token', transaction_type: 'MOTO')
+ end.check_request do |endpoint, data, headers|
+ assert_match '"Method":"TokenPayment"', data
+ assert_match '"TransactionType":"MOTO"', data
+ end.respond_with(successful_store_purchase_response)
- @gateway.store(@credit_card, options)
+ assert_success response
+ assert_equal "Transaction Approved Successful", response.message
+ assert_equal 10440234, response.authorization
+ assert response.test?
end
def test_verification_results
response = stub_comms do
- @gateway.status("thetransauth")
- end.respond_with(successful_status_response(:verification_status => "Valid"))
+ @gateway.purchase(100, @credit_card)
+ end.respond_with(successful_purchase_response(:verification_status => "Valid"))
assert_success response
assert_equal "M", response.cvv_result["code"]
assert_equal "M", response.avs_result["code"]
response = stub_comms do
- @gateway.status("thetransauth")
- end.respond_with(successful_status_response(:verification_status => "Invalid"))
+ @gateway.purchase(100, @credit_card)
+ end.respond_with(successful_purchase_response(:verification_status => "Invalid"))
assert_success response
assert_equal "N", response.cvv_result["code"]
assert_equal "N", response.avs_result["code"]
response = stub_comms do
- @gateway.status("thetransauth")
- end.respond_with(successful_status_response(:verification_status => "Unchecked"))
+ @gateway.purchase(100, @credit_card)
+ end.respond_with(successful_purchase_response(:verification_status => "Unchecked"))
assert_success response
assert_equal "P", response.cvv_result["code"]
@@ -248,148 +251,452 @@ def test_verification_results
private
- def successful_setup_purchase_response
+ def successful_purchase_response(options = {})
+ verification_status = options[:verification_status] || 0
+ verification_status = %Q{"#{verification_status}"} if verification_status.is_a? String
%(
-
- 60CF3xWrFUQeDCEsJcA8zNHaspAT3CKpe-0DiqWjTYA3RZw1xhw2LU-BFCNYbr7eJt8KFaxCxmzYh9WDAYX8yIuYexTq0tC8i2kOt0dm0EV-mjxYEQ2YeHP2dazkSc7j58OiT
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- false
-
-
- 100
- Store Purchase
- 1
- AUD
-
- https://secure-au.sandbox.ewaypayments.com/Process
-
+ {
+ "AuthorisationCode": "763051",
+ "ResponseCode": "00",
+ "ResponseMessage": "A2000",
+ "TransactionID": 10440187,
+ "TransactionStatus": true,
+ "TransactionType": "Purchase",
+ "BeagleScore": 0,
+ "Verification": {
+ "CVN": #{verification_status},
+ "Address": #{verification_status},
+ "Email": #{verification_status},
+ "Mobile": #{verification_status},
+ "Phone": #{verification_status}
+ },
+ "Customer": {
+ "CardDetails": {
+ "Number": "444433XXXXXX1111",
+ "Name": "Longbob Longsen",
+ "ExpiryMonth": "09",
+ "ExpiryYear": "14",
+ "StartMonth": null,
+ "StartYear": null,
+ "IssueNumber": null
+ },
+ "TokenCustomerID": null,
+ "Reference": "",
+ "Title": "Mr.",
+ "FirstName": "Jim",
+ "LastName": "Smith",
+ "CompanyName": "Widgets Inc",
+ "JobDescription": "",
+ "Street1": "1234 My Street",
+ "Street2": "Apt 1",
+ "City": "Ottawa",
+ "State": "ON",
+ "PostalCode": "K1C2N6",
+ "Country": "ca",
+ "Email": "",
+ "Phone": "(555)555-5555",
+ "Mobile": "",
+ "Comments": "",
+ "Fax": "(555)555-6666",
+ "Url": ""
+ },
+ "Payment": {
+ "TotalAmount": 100,
+ "InvoiceNumber": "",
+ "InvoiceDescription": "Store Purchase",
+ "InvoiceReference": "1",
+ "CurrencyCode": "AUD"
+ },
+ "Errors": null
+ }
)
end
- def failed_setup_purchase_response
+ def failed_purchase_response
%(
-
- V6047
-
-
- false
-
-
- 100
- AUD
-
-
+ {
+ "AuthorisationCode": null,
+ "ResponseCode": null,
+ "ResponseMessage": null,
+ "TransactionID": null,
+ "TransactionStatus": null,
+ "TransactionType": "Purchase",
+ "BeagleScore": null,
+ "Verification": null,
+ "Customer": {
+ "CardDetails": {
+ "Number": "444433XXXXXX1111",
+ "Name": "Longbob Longsen",
+ "ExpiryMonth": "09",
+ "ExpiryYear": "2014",
+ "StartMonth": null,
+ "StartYear": null,
+ "IssueNumber": null
+ },
+ "TokenCustomerID": null,
+ "Reference": null,
+ "Title": "Mr.",
+ "FirstName": "Jim",
+ "LastName": "Smith",
+ "CompanyName": "Widgets Inc",
+ "JobDescription": null,
+ "Street1": "1234 My Street",
+ "Street2": "Apt 1",
+ "City": "Ottawa",
+ "State": "ON",
+ "PostalCode": "K1C2N6",
+ "Country": "ca",
+ "Email": null,
+ "Phone": "(555)555-5555",
+ "Mobile": null,
+ "Comments": null,
+ "Fax": "(555)555-6666",
+ "Url": null
+ },
+ "Payment": {
+ "TotalAmount": -100,
+ "InvoiceNumber": null,
+ "InvoiceDescription": "Store Purchase",
+ "InvoiceReference": "1",
+ "CurrencyCode": "AUD"
+ },
+ "Errors": "V6011"
+ }
)
end
- def successful_status_response(options={})
- verification_status = (options[:verification_status] || "Unchecked")
+ def successful_store_response
%(
-
- 60CF3sfH7-yvAsUAHrdIiGppPrQW7v7DMAXxKkaKwyrIUoqvUvK44XbK9G9HNbngIz_iwQpfmPT_duMgh2G0pXCX8i4z1RAmMHpUQwa6VrghV3Bx9rh_tojjym7LC_fE-eR97
- 957199
- 00
- A2000
-
- orderid1
- 100
- 9942726
- true
-
- 0
-
-
- #{verification_status}
- #{verification_status}
- #{verification_status}
- #{verification_status}
- #{verification_status}
-
-
+ {
+ "AuthorisationCode": null,
+ "ResponseCode": "00",
+ "ResponseMessage": "A2000",
+ "TransactionID": null,
+ "TransactionStatus": false,
+ "TransactionType": "Purchase",
+ "BeagleScore": null,
+ "Verification": {
+ "CVN": 0,
+ "Address": 0,
+ "Email": 0,
+ "Mobile": 0,
+ "Phone": 0
+ },
+ "Customer": {
+ "CardDetails": {
+ "Number": "444433XXXXXX1111",
+ "Name": "Longbob Longsen",
+ "ExpiryMonth": "09",
+ "ExpiryYear": "14",
+ "StartMonth": null,
+ "StartYear": null,
+ "IssueNumber": null
+ },
+ "TokenCustomerID": 917224224772,
+ "Reference": "",
+ "Title": "Dr.",
+ "FirstName": "Jim",
+ "LastName": "Smith",
+ "CompanyName": "Widgets Inc",
+ "JobDescription": "",
+ "Street1": "1234 My Street",
+ "Street2": "Apt 1",
+ "City": "Ottawa",
+ "State": "ON",
+ "PostalCode": "K1C2N6",
+ "Country": "ca",
+ "Email": "",
+ "Phone": "(555)555-5555",
+ "Mobile": "",
+ "Comments": "",
+ "Fax": "(555)555-6666",
+ "Url": ""
+ },
+ "Payment": {
+ "TotalAmount": 0,
+ "InvoiceNumber": "",
+ "InvoiceDescription": "Store Purchase",
+ "InvoiceReference": "1",
+ "CurrencyCode": "AUD"
+ },
+ "Errors": null
+ }
)
end
- def failed_status_response
+ def failed_store_response
%(
-
- A1001WfAHR_QP8daLnG6fQLcadzuCBJbpIp-zsUL6FkQgUyY2MXwVA0etYvflPe_rDBiuOMV-BfTSGDKt7uU3E2bLUhsD1rrXwGT9BTPcOOH_Vh9jHDSn2inqk8udwQIRcxuc
-
- 05
- D4405
-
- 1
- 105
- 9942743
- false
-
- 0
-
-
- Unchecked
- Unchecked
- Unchecked
- Unchecked
- Unchecked
-
-
+ {
+ "AuthorisationCode": null,
+ "ResponseCode": null,
+ "ResponseMessage": null,
+ "TransactionID": null,
+ "TransactionStatus": null,
+ "TransactionType": "Purchase",
+ "BeagleScore": null,
+ "Verification": null,
+ "Customer": {
+ "CardDetails": {
+ "Number": "444433XXXXXX1111",
+ "Name": "Longbob Longsen",
+ "ExpiryMonth": "09",
+ "ExpiryYear": "2014",
+ "StartMonth": null,
+ "StartYear": null,
+ "IssueNumber": null
+ },
+ "TokenCustomerID": null,
+ "Reference": null,
+ "Title": "Mr.",
+ "FirstName": "Jim",
+ "LastName": "Smith",
+ "CompanyName": "Widgets Inc",
+ "JobDescription": null,
+ "Street1": "1234 My Street",
+ "Street2": "Apt 1",
+ "City": "Ottawa",
+ "State": "ON",
+ "PostalCode": "K1C2N6",
+ "Country": null,
+ "Email": null,
+ "Phone": "(555)555-5555",
+ "Mobile": null,
+ "Comments": null,
+ "Fax": "(555)555-6666",
+ "Url": null
+ },
+ "Payment": {
+ "TotalAmount": 0,
+ "InvoiceNumber": null,
+ "InvoiceDescription": "Store Purchase",
+ "InvoiceReference": "1",
+ "CurrencyCode": "AUD"
+ },
+ "Errors": "V6044"
+ }
)
end
- class MockResponse
- attr_reader :code, :body
- def initialize(code, body, headers={})
- @code, @body, @headers = code, body, headers
- end
+ def successful_update_response
+ %(
+ {
+ "AuthorisationCode": null,
+ "ResponseCode": "00",
+ "ResponseMessage": "A2000",
+ "TransactionID": null,
+ "TransactionStatus": false,
+ "TransactionType": "Purchase",
+ "BeagleScore": null,
+ "Verification": {
+ "CVN": 0,
+ "Address": 0,
+ "Email": 0,
+ "Mobile": 0,
+ "Phone": 0
+ },
+ "Customer": {
+ "CardDetails": {
+ "Number": "444433XXXXXX1111",
+ "Name": "Longbob Longsen",
+ "ExpiryMonth": "09",
+ "ExpiryYear": "14",
+ "StartMonth": null,
+ "StartYear": null,
+ "IssueNumber": null
+ },
+ "TokenCustomerID": 916161208398,
+ "Reference": "",
+ "Title": "Dr.",
+ "FirstName": "Jim",
+ "LastName": "Smith",
+ "CompanyName": "Widgets Inc",
+ "JobDescription": "",
+ "Street1": "1234 My Street",
+ "Street2": "Apt 1",
+ "City": "Ottawa",
+ "State": "ON",
+ "PostalCode": "K1C2N6",
+ "Country": "ca",
+ "Email": "",
+ "Phone": "(555)555-5555",
+ "Mobile": "",
+ "Comments": "",
+ "Fax": "(555)555-6666",
+ "Url": ""
+ },
+ "Payment": {
+ "TotalAmount": 0,
+ "InvoiceNumber": "",
+ "InvoiceDescription": "Store Purchase",
+ "InvoiceReference": "1",
+ "CurrencyCode": "AUD"
+ },
+ "Errors": null
+ }
+ )
+ end
- def [](header)
- @headers[header]
- end
+ def successful_refund_response
+ %(
+ {
+ "AuthorisationCode": "457313",
+ "ResponseCode": null,
+ "ResponseMessage": "A2000",
+ "TransactionID": 10488258,
+ "TransactionStatus": true,
+ "Verification": null,
+ "Customer": {
+ "CardDetails": {
+ "Number": null,
+ "Name": null,
+ "ExpiryMonth": null,
+ "ExpiryYear": null,
+ "StartMonth": null,
+ "StartYear": null,
+ "IssueNumber": null
+ },
+ "TokenCustomerID": null,
+ "Reference": null,
+ "Title": null,
+ "FirstName": "Jim",
+ "LastName": "Smith",
+ "CompanyName": "Widgets Inc",
+ "JobDescription": null,
+ "Street1": "1234 My Street",
+ "Street2": "Apt 1",
+ "City": "Ottawa",
+ "State": "ON",
+ "PostalCode": "K1C2N6",
+ "Country": "ca",
+ "Email": null,
+ "Phone": "(555)555-5555",
+ "Mobile": null,
+ "Comments": null,
+ "Fax": "(555)555-6666",
+ "Url": null
+ },
+ "Refund": {
+ "TransactionID": null,
+ "TotalAmount": 0,
+ "InvoiceNumber": null,
+ "InvoiceDescription": null,
+ "InvoiceReference": null,
+ "CurrencyCode": null
+ },
+ "Errors": null
+ }
+ )
end
- def successful_run_purchase_response
- MockResponse.new(
- 302,
- %(
- Object moved
- Object moved to here.
-
- ),
- "Location" => "http://example.com/?AccessCode=60CF3xWrFUQeDCEsJcA8zNHaspAT3CKpe-0DiqWjTYA3RZw1xhw2LU-BFCNYbr7eJt8KFaxCxmzYh9WDAYX8yIuYexTq0tC8i2kOt0dm0EV-mjxYEQ2YeHP2dazkSc7j58OiT"
+ def failed_refund_response
+ %(
+ {
+ "AuthorisationCode": null,
+ "ResponseCode": null,
+ "ResponseMessage": null,
+ "TransactionID": null,
+ "TransactionStatus": false,
+ "Verification": null,
+ "Customer": {
+ "CardDetails": {
+ "Number": null,
+ "Name": null,
+ "ExpiryMonth": null,
+ "ExpiryYear": null,
+ "StartMonth": null,
+ "StartYear": null,
+ "IssueNumber": null
+ },
+ "TokenCustomerID": null,
+ "Reference": null,
+ "Title": null,
+ "FirstName": "Jim",
+ "LastName": "Smith",
+ "CompanyName": "Widgets Inc",
+ "JobDescription": null,
+ "Street1": "1234 My Street",
+ "Street2": "Apt 1",
+ "City": "Ottawa",
+ "State": "ON",
+ "PostalCode": "K1C2N6",
+ "Country": "ca",
+ "Email": null,
+ "Phone": "(555)555-5555",
+ "Mobile": null,
+ "Comments": null,
+ "Fax": "(555)555-6666",
+ "Url": null
+ },
+ "Refund": {
+ "TransactionID": null,
+ "TotalAmount": 0,
+ "InvoiceNumber": null,
+ "InvoiceDescription": null,
+ "InvoiceReference": null,
+ "CurrencyCode": null
+ },
+ "Errors": "S5000"
+ }
)
end
- def failed_run_purchase_response
- MockResponse.new(
- 200,
- %(
- {"Message":"Not Found","Errors":null}
- )
+ def successful_store_purchase_response
+ %(
+ {
+ "AuthorisationCode": "232671",
+ "ResponseCode": "00",
+ "ResponseMessage": "A2000",
+ "TransactionID": 10440234,
+ "TransactionStatus": true,
+ "TransactionType": "MOTO",
+ "BeagleScore": 0,
+ "Verification": {
+ "CVN": 0,
+ "Address": 0,
+ "Email": 0,
+ "Mobile": 0,
+ "Phone": 0
+ },
+ "Customer": {
+ "CardDetails": {
+ "Number": "444433XXXXXX1111",
+ "Name": "Longbob Longsen",
+ "ExpiryMonth": "09",
+ "ExpiryYear": "14",
+ "StartMonth": "",
+ "StartYear": "",
+ "IssueNumber": ""
+ },
+ "TokenCustomerID": 912056757740,
+ "Reference": "",
+ "Title": "Mr.",
+ "FirstName": "Jim",
+ "LastName": "Smith",
+ "CompanyName": "Widgets Inc",
+ "JobDescription": "",
+ "Street1": "1234 My Street, Apt 1",
+ "Street2": "",
+ "City": "Ottawa",
+ "State": "ON",
+ "PostalCode": "K1C2N6",
+ "Country": "ca",
+ "Email": "",
+ "Phone": "(555)555-5555",
+ "Mobile": "",
+ "Comments": "",
+ "Fax": "(555)555-6666",
+ "Url": ""
+ },
+ "Payment": {
+ "TotalAmount": 100,
+ "InvoiceNumber": "",
+ "InvoiceDescription": "",
+ "InvoiceReference": "",
+ "CurrencyCode": "AUD"
+ },
+ "Errors": null
+ }
)
end
+
end
diff --git a/test/unit/gateways/gateway_test.rb b/test/unit/gateways/gateway_test.rb
index 2bef0185402..ef1557b0cf2 100644
--- a/test/unit/gateways/gateway_test.rb
+++ b/test/unit/gateways/gateway_test.rb
@@ -1,6 +1,14 @@
require 'test_helper'
class GatewayTest < Test::Unit::TestCase
+ def setup
+ @gateway = Gateway.new
+ end
+
+ def teardown
+ Gateway.money_format = :dollars
+ end
+
def test_should_detect_if_a_card_is_supported
Gateway.supported_cardtypes = [:visa, :bogus]
assert [:visa, :bogus].all? { |supported_cardtype| Gateway.supports?(supported_cardtype) }
@@ -15,17 +23,17 @@ def test_should_gateway_uses_ssl_strict_checking_by_default
def test_should_be_able_to_look_for_test_mode
Base.gateway_mode = :test
- assert Gateway.new.test?
+ assert @gateway.test?
Base.gateway_mode = :production
- assert_false Gateway.new.test?
+ assert_false @gateway.test?
end
def test_amount_style
- assert_equal '10.34', Gateway.new.send(:amount, 1034)
+ assert_equal '10.34', @gateway.send(:amount, 1034)
assert_raise(ArgumentError) do
- Gateway.new.send(:amount, '10.34')
+ @gateway.send(:amount, '10.34')
end
end
@@ -45,4 +53,24 @@ def test_setting_application_id_outside_the_class_definition
assert_equal SimpleTestGateway.application_id, SubclassGateway.application_id
end
+
+ def test_localized_amount_should_not_modify_for_fractional_currencies
+ Gateway.money_format = :dollars
+ assert_equal '1.00', @gateway.send(:localized_amount, 100, 'CAD')
+ assert_equal '12.34', @gateway.send(:localized_amount, 1234, 'USD')
+
+ Gateway.money_format = :cents
+ assert_equal '100', @gateway.send(:localized_amount, 100, 'CAD')
+ assert_equal '1234', @gateway.send(:localized_amount, 1234, 'USD')
+ end
+
+ def test_localized_amount_should_ignore_money_format_for_non_fractional_currencies
+ Gateway.money_format = :dollars
+ assert_equal '1', @gateway.send(:localized_amount, 100, 'JPY')
+ assert_equal '12', @gateway.send(:localized_amount, 1234, 'HUF')
+
+ Gateway.money_format = :cents
+ assert_equal '1', @gateway.send(:localized_amount, 100, 'JPY')
+ assert_equal '12', @gateway.send(:localized_amount, 1234, 'HUF')
+ end
end
diff --git a/test/unit/gateways/litle_test.rb b/test/unit/gateways/litle_test.rb
index e3166870e8f..8ca342b3e0c 100755
--- a/test/unit/gateways/litle_test.rb
+++ b/test/unit/gateways/litle_test.rb
@@ -377,6 +377,7 @@ def test_auth_pass
assert_equal 'successful', responseFrom.message
assert_equal '1234;authorization', responseFrom.authorization
assert_equal '1111222233334444', responseFrom.params['litleOnlineResponse']['authorizationResponse']['litleToken']
+ assert_equal '000', responseFrom.params['response_code']
end
def test_avs
diff --git a/test/unit/gateways/nab_transact_test.rb b/test/unit/gateways/nab_transact_test.rb
index 126d9cde318..09c4b5c7105 100644
--- a/test/unit/gateways/nab_transact_test.rb
+++ b/test/unit/gateways/nab_transact_test.rb
@@ -1,6 +1,8 @@
require 'test_helper'
class NabTransactTest < Test::Unit::TestCase
+ include CommStub
+
def setup
@gateway = NabTransactGateway.new(
:login => 'login',
@@ -16,7 +18,6 @@ def setup
}
end
-
def test_successful_purchase
@gateway.expects(:ssl_post).with(&check_transaction_type(:purchase)).returns(successful_purchase_response)
@@ -28,6 +29,18 @@ def test_successful_purchase
assert response.test?
end
+ def test_successful_purchase_with_merchant_descriptor
+ name, location = 'Active Merchant', 'USA'
+
+ response = assert_metadata(name, location) do
+ response = @gateway.purchase(@amount, @credit_card, @options.merge(:merchant_name => name, :merchant_location => location))
+ end
+
+ assert response
+ assert_instance_of Response, response
+ assert_success response
+ end
+
def test_successful_authorize
@gateway.expects(:ssl_post).with(&check_transaction_type(:authorization)).returns(successful_authorize_response)
assert response = @gateway.authorize(@amount, @credit_card, @options)
@@ -35,6 +48,18 @@ def test_successful_authorize
assert response.test?
end
+ def test_successful_authorize_with_merchant_descriptor
+ name, location = 'Active Merchant', 'USA'
+
+ response = assert_metadata(name, location) do
+ response = @gateway.authorize(@amount, @credit_card, @options.merge(:merchant_name => name, :merchant_location => location))
+ end
+
+ assert response
+ assert_instance_of Response, response
+ assert_success response
+ end
+
def test_successful_capture
@gateway.expects(:ssl_post).with(&check_transaction_type(:capture)).returns(successful_purchase_response)
assert response = @gateway.capture(@amount, '009887*test*009887*200')
@@ -42,6 +67,18 @@ def test_successful_capture
assert response.test?
end
+ def test_successful_capture_with_merchant_descriptor
+ name, location = 'Active Merchant', 'USA'
+
+ response = assert_metadata(name, location) do
+ response = @gateway.capture(@amount, '009887*test*009887*200', @options.merge(:merchant_name => name, :merchant_location => location))
+ end
+
+ assert response
+ assert_instance_of Response, response
+ assert_success response
+ end
+
def test_unsuccessful_purchase
@gateway.expects(:ssl_post).with(&check_transaction_type(:purchase)).returns(failed_purchase_response)
@@ -74,6 +111,18 @@ def test_successful_refund
assert_success @gateway.refund(@amount, "009887", {:order_id => '1'})
end
+ def test_successful_refund_with_merchant_descriptor
+ name, location = 'Active Merchant', 'USA'
+
+ response = assert_metadata(name, location) do
+ response = @gateway.refund(@amount, '009887', {:order_id => '1', :merchant_name => name, :merchant_location => location})
+ end
+
+ assert response
+ assert_instance_of Response, response
+ assert_success response
+ end
+
def test_failed_refund
@gateway.expects(:ssl_post).with(&check_transaction_type(:refund)).returns(failed_refund_response)
@@ -91,6 +140,20 @@ def check_transaction_type(type)
end
end
+ def valid_metadata(name, location)
+ valid_metadata = <<-XML.gsub(/^\s{4}/,'').gsub(/\n/, '')
+
+ XML
+ end
+
+ def assert_metadata(name, location, &block)
+ stub_comms(@gateway, :ssl_request) do
+ block.call
+ end.check_request do |method, endpoint, data, headers|
+ metadata_matcher = Regexp.escape(valid_metadata(name, location))
+ assert_match /#{metadata_matcher}/, data
+ end.respond_with(successful_purchase_response)
+ end
def failed_login_response
'504Invalid merchant ID'
diff --git a/test/unit/gateways/orbital_test.rb b/test/unit/gateways/orbital_test.rb
index 667b054ab22..99db6eceb75 100644
--- a/test/unit/gateways/orbital_test.rb
+++ b/test/unit/gateways/orbital_test.rb
@@ -22,6 +22,26 @@ def test_successful_purchase
assert_equal '4A5398CF9B87744GG84A1D30F2F2321C66249416;1', response.authorization
end
+ def test_currency_exponents
+ stub_comms do
+ @gateway.purchase(50, credit_card, :order_id => '1')
+ end.check_request do |endpoint, data, headers|
+ assert_match /2<\/CurrencyExponent>/, data
+ end.respond_with(successful_purchase_response)
+
+ stub_comms do
+ @gateway.purchase(50, credit_card, :order_id => '1', :currency => 'CAD')
+ end.check_request do |endpoint, data, headers|
+ assert_match /2<\/CurrencyExponent>/, data
+ end.respond_with(successful_purchase_response)
+
+ stub_comms do
+ @gateway.purchase(50, credit_card, :order_id => '1', :currency => 'JPY')
+ end.check_request do |endpoint, data, headers|
+ assert_match /0<\/CurrencyExponent>/, data
+ end.respond_with(successful_purchase_response)
+ end
+
def test_unauthenticated_response
@gateway.expects(:ssl_post).returns(failed_purchase_response)
@@ -259,6 +279,30 @@ def test_send_customer_data_when_customer_ref_is_provided
assert_success response
end
+ def test_currency_code_and_exponent_are_set_for_profile_purchase
+ @gateway.options[:customer_profiles] = true
+ response = stub_comms do
+ @gateway.purchase(50, nil, :order_id => 1, :customer_ref_num => @customer_ref_num)
+ end.check_request do |endpoint, data, headers|
+ assert_match(/ABC/, data)
+ assert_match(/124/, data)
+ assert_match(/2/, data)
+ end.respond_with(successful_purchase_response)
+ assert_success response
+ end
+
+ def test_currency_code_and_exponent_are_set_for_profile_authorizations
+ @gateway.options[:customer_profiles] = true
+ response = stub_comms do
+ @gateway.authorize(50, nil, :order_id => 1, :customer_ref_num => @customer_ref_num)
+ end.check_request do |endpoint, data, headers|
+ assert_match(/ABC/, data)
+ assert_match(/124/, data)
+ assert_match(/2/, data)
+ end.respond_with(successful_purchase_response)
+ assert_success response
+ end
+
# K1C2N6
# 1234 My Street
# Apt 1
diff --git a/test/unit/gateways/pac_net_raven_test.rb b/test/unit/gateways/pac_net_raven_test.rb
new file mode 100644
index 00000000000..1727b63fb32
--- /dev/null
+++ b/test/unit/gateways/pac_net_raven_test.rb
@@ -0,0 +1,541 @@
+require 'test_helper'
+
+class PacNetRavenGatewayTest < Test::Unit::TestCase
+ def setup
+ @gateway = PacNetRavenGateway.new(
+ user: 'user',
+ secret: 'secret',
+ prn: 123456
+ )
+
+ @credit_card = credit_card
+ @amount = 100
+
+ @options = {
+ billing_address: address
+ }
+ end
+
+ def test_successful_authorization
+ @gateway.expects(:ssl_post).returns(successful_authorization_response)
+ assert response = @gateway.purchase(@amount, @credit_card, @options)
+ assert_instance_of Response, response
+ assert_success response
+ assert_equal 'This transaction has been approved', response.message
+ assert_equal '123456789', response.authorization
+ assert response.test?
+ end
+
+ def test_invalid_credit_card_authorization
+ @gateway.expects(:ssl_post).returns(invalid_credit_card_response)
+ assert response = @gateway.authorize(@amount, @credit_card, @options)
+ assert_failure response
+ assert_equal "Error processing transaction because CardNumber is not between 12 and 19 in length", response.message
+ end
+
+ def test_expired_credit_card_authorization
+ @gateway.expects(:ssl_post).returns(expired_credit_card_response)
+ assert response = @gateway.authorize(@amount, @credit_card, @options)
+ assert_failure response
+ assert_equal "Invalid because the card expiry date is not a date in the future", response.message
+ end
+
+ def test_declined_authorization
+ @gateway.expects(:ssl_post).returns(declined_purchese_response)
+ assert response = @gateway.authorize(@amount, @credit_card, @options)
+ assert_failure response
+ assert_equal 'This transaction has been declined', response.message
+ end
+
+ def test_successful_purchase
+ @gateway.expects(:ssl_post).returns(successful_purchase_response)
+ assert response = @gateway.purchase(@amount, @credit_card, @options)
+ assert_instance_of Response, response
+ assert_success response
+ assert_equal 'This transaction has been approved', response.message
+ assert_equal '123456789', response.authorization
+ assert response.test?
+ end
+
+ def test_invalid_credit_card_number_purchese
+ @gateway.expects(:ssl_post).returns(invalid_credit_card_response)
+ assert response = @gateway.purchase(@amount, @credit_card, @options)
+ assert_failure response
+ assert_equal "Error processing transaction because CardNumber is not between 12 and 19 in length", response.message
+ end
+
+ def test_expired_credit_card_purchese
+ @gateway.expects(:ssl_post).returns(expired_credit_card_response)
+ assert response = @gateway.purchase(@amount, @credit_card, @options)
+ assert_failure response
+ assert_equal "Invalid because the card expiry date is not a date in the future", response.message
+ end
+
+ def test_declined_purchese
+ @gateway.expects(:ssl_post).returns(declined_purchese_response)
+ assert response = @gateway.purchase(@amount, @credit_card, @options)
+ assert_failure response
+ assert_equal 'This transaction has been declined', response.message
+ end
+
+ def test_successful_capture
+ @gateway.expects(:ssl_post).returns(successful_capture_response)
+ assert response = @gateway.capture(@amount, '123456789')
+ assert_instance_of Response, response
+ assert_success response
+ assert_equal 'This transaction has been approved', response.message
+ assert_equal '123456789', response.authorization
+ assert response.test?
+ end
+
+ def test_invalid_preauth_number_capture
+ @gateway.expects(:ssl_post).returns(invalid_preauth_number_response)
+ assert response = @gateway.capture(@amount, '')
+ assert_failure response
+ assert_equal 'Error processing transaction because the pre-auth number', response.message
+ end
+
+ def test_insufficient_preauth_amount_capture
+ @gateway.expects(:ssl_post).returns(insufficient_preauth_amount_response)
+ assert response = @gateway.capture(200, '123456789')
+ assert_failure response
+ assert_equal 'Invalid because the preauthorization amount 100 is insufficient', response.message
+ end
+
+ def test_successful_refund
+ @gateway.expects(:ssl_post).returns(successful_refund_response)
+ assert response = @gateway.refund(@amount, '123456789')
+ assert_success response
+ assert_equal 'This transaction has been approved', response.message
+ end
+
+ def test_amount_greater_than_original_amount_refund
+ @gateway.expects(:ssl_post).returns(amount_greater_than_original_amount_refund_response)
+ assert response = @gateway.refund(200, '123456789')
+ assert_failure response
+ assert_equal 'Invalid because the payment amount cannot be greater than the original charge', response.message
+ end
+
+ def test_successful_void
+ @gateway.expects(:ssl_post).returns(successful_void_response)
+ assert response = @gateway.void('123456789')
+ assert_success response
+ assert_equal "This transaction has been voided", response.message
+ end
+
+ def test_failed_void
+ @gateway.expects(:ssl_post).returns(failed_void_response)
+ assert response = @gateway.void('123456789')
+ assert_failure response
+ assert_equal "Error processing transaction because the payment may not be voided", response.message
+ end
+
+ def test_argument_error_prn
+ exception = assert_raises(ArgumentError){
+ PacNetRavenGateway.new(:user => 'user', :secret => 'secret')
+ }
+ assert_equal 'Missing required parameter: prn', exception.message
+ end
+
+ def test_argument_error_user
+ exception = assert_raises(ArgumentError){
+ PacNetRavenGateway.new(:secret => 'secret', :prn => 123456)
+ }
+ assert_equal 'Missing required parameter: user', exception.message
+ end
+
+ def test_argument_error_secret
+ exception = assert_raises(ArgumentError){
+ PacNetRavenGateway.new(:user => 'user', :prn => 123456)
+ }
+ assert_equal 'Missing required parameter: secret', exception.message
+ end
+
+ def test_add_address
+ result = {}
+ @gateway.send(:add_address, result, :billing_address => {:address1 => 'Address 1', :address2 => 'Address 2', :zip => 'ZIP'} )
+ assert_equal ["BillingPostalCode", "BillingStreetAddressLineFour", "BillingStreetAddressLineOne"], result.stringify_keys.keys.sort
+ assert_equal 'ZIP', result['BillingPostalCode']
+ assert_equal 'Address 2', result['BillingStreetAddressLineFour']
+ assert_equal 'Address 1', result['BillingStreetAddressLineOne']
+ end
+
+ def test_add_creditcard
+ result = {}
+ @gateway.send(:add_creditcard, result, @credit_card)
+ assert_equal ["CVV2", "CardNumber", "Expiry"], result.stringify_keys.keys.sort
+ assert_equal @credit_card.number, result['CardNumber']
+ assert_equal @gateway.send(:expdate, @credit_card), result['Expiry']
+ assert_equal @credit_card.verification_value, result['CVV2']
+ end
+
+ def test_add_currency_code_default
+ result = {}
+ @gateway.send(:add_currency_code, result, 100, {})
+ assert_equal 'USD', result['Currency']
+ end
+
+ def test_add_currency_code_from_options
+ result = {}
+ @gateway.send(:add_currency_code, result, 100, {currency: 'CAN'})
+ assert_equal 'CAN', result['Currency']
+ end
+
+ def test_parse
+ result = @gateway.send(:parse, "key1=value1&key2=value2")
+ h = {'key1' => 'value1', 'key2' => 'value2'}
+ assert_equal h, result
+ end
+
+ def test_endpoint_for_void
+ assert_equal 'void', @gateway.send(:endpoint, 'void')
+ end
+
+ def test_endpoint_for_cc_debit
+ assert_equal 'submit', @gateway.send(:endpoint, 'cc_debit')
+ end
+
+ def test_endpoint_for_cc_preauth
+ assert_equal 'submit', @gateway.send(:endpoint, 'cc_preauth')
+ end
+
+ def test_endpoint_for_cc_settle
+ assert_equal 'submit', @gateway.send(:endpoint, 'cc_settle')
+ end
+
+ def test_endpoint_for_cc_refund
+ assert_equal 'submit', @gateway.send(:endpoint, 'cc_refund')
+ end
+
+ def test_success
+ assert @gateway.send(:success?, {
+ :action => 'cc_settle',
+ 'ApprovalCode' => '123456',
+ 'ErrorCode' => nil,
+ 'Status' => 'Approved'
+ })
+
+ refute @gateway.send(:success?, {
+ :action => 'cc_settle',
+ 'ApprovalCode' => nil,
+ 'ErrorCode' => 'SomeError',
+ 'Status' => 'SomeError'
+ })
+
+ assert @gateway.send(:success?, {
+ :action => 'cc_debit',
+ 'ApprovalCode' => '123456',
+ 'ErrorCode' => nil,
+ 'Status' => 'Approved'
+ })
+
+ refute @gateway.send(:success?, {
+ :action => 'cc_debit',
+ 'ApprovalCode' => nil,
+ 'ErrorCode' => 'SomeError',
+ 'Status' => 'SomeError'
+ })
+
+ assert @gateway.send(:success?, {
+ :action => 'cc_preauth',
+ 'ApprovalCode' => '123456',
+ 'ErrorCode' => nil,
+ 'Status' => 'Approved'
+ })
+
+ refute @gateway.send(:success?, {
+ :action => 'cc_preauth',
+ 'ApprovalCode' => nil,
+ 'ErrorCode' => 'SomeError',
+ 'Status' => 'SomeError'
+ })
+
+ assert @gateway.send(:success?, {
+ :action => 'cc_refund',
+ 'ApprovalCode' => '123456',
+ 'ErrorCode' => nil,
+ 'Status' => 'Approved'
+ })
+
+ refute @gateway.send(:success?, {
+ :action => 'cc_refund',
+ 'ApprovalCode' => nil,
+ 'ErrorCode' => 'SomeError',
+ 'Status' => 'SomeError'
+ })
+
+ assert @gateway.send(:success?, {
+ :action => 'void',
+ 'ApprovalCode' => '123456',
+ 'ErrorCode' => nil,
+ 'Status' => 'Voided'
+ })
+
+ refute @gateway.send(:success?, {
+ :action => 'void',
+ 'ApprovalCode' => nil,
+ 'ErrorCode' => 'SomeError',
+ 'Status' => 'SomeError'
+ })
+ end
+
+ def test_message_from_approved
+ assert_equal "This transaction has been approved", @gateway.send(:message_from, {
+ 'Status' => 'Approved',
+ 'Message'=> nil
+ })
+ end
+
+ def test_message_from_declined
+ assert_equal "This transaction has been declined", @gateway.send(:message_from, {
+ 'Status' => 'Declined',
+ 'Message'=> nil
+ })
+ end
+
+ def test_message_from_voided
+ assert_equal "This transaction has been voided", @gateway.send(:message_from, {
+ 'Status' => 'Voided',
+ 'Message'=> nil
+ })
+ end
+
+ def test_message_from_status
+ assert_equal "This is the message", @gateway.send(:message_from, {
+ 'Status' => 'SomeStatus',
+ 'Message'=> "This is the message"
+ })
+ end
+
+ def test_post_data
+ @gateway.stubs(:request_id => "wouykiikdvqbwwxueppby")
+ @gateway.stubs(:timestamp => "2013-10-08T14:31:54.Z")
+
+ assert_equal "PymtType=cc_preauth&RAPIVersion=2&UserName=user&Timestamp=2013-10-08T14%3A31%3A54.Z&RequestID=wouykiikdvqbwwxueppby&Signature=7794efc8c0d39f0983edc10f778e6143ba13531d&CardNumber=4242424242424242&Expiry=0914&CVV2=123&Currency=USD&BillingStreetAddressLineOne=Address+1&BillingStreetAddressLineFour=Address+2&BillingPostalCode=ZIP123",
+ @gateway.send(:post_data, 'cc_preauth', {
+ 'CardNumber' => @credit_card.number,
+ 'Expiry' => @gateway.send(:expdate, @credit_card),
+ 'CVV2' => @credit_card.verification_value,
+ 'Currency' => 'USD',
+ 'BillingStreetAddressLineOne' => 'Address 1',
+ 'BillingStreetAddressLineFour' => 'Address 2',
+ 'BillingPostalCode' => 'ZIP123'
+ })
+ end
+
+ def test_signature_for_cc_preauth_action
+ assert_equal 'd5ff154d6631333c21d0c78975b3bf5d9ccd0ef8', @gateway.send(:signature, 'cc_preauth', {
+ 'UserName' => 'user',
+ 'Timestamp' => '2013-10-08T14:31:54.Z',
+ 'RequestID' => 'wouykiikdvqbwwxueppby',
+ 'PymtType' => 'cc_preauth'
+ }, {
+ 'Amount' => 100,
+ 'Currency' => 'USD',
+ 'TrackingNumber' => '123456789'
+ })
+ end
+
+ def test_signature_for_cc_settle_action
+ assert_equal 'c80cccf6c77438785726b5a447d5aed84738c6d1', @gateway.send(:signature, 'cc_settle', {
+ 'UserName' => 'user',
+ 'Timestamp' => '2013-10-08T14:31:54.Z',
+ 'RequestID' => 'wouykiikdvqbwwxueppby',
+ 'PymtType' => 'cc_settle'
+ }, {
+ 'Amount' => 100,
+ 'Currency' => 'USD',
+ 'TrackingNumber' => '123456789'
+ })
+ end
+
+ def test_signature_for_cc_debit_action
+ assert_equal 'b2a0eb307cfd092152d44b06a49a360feccdb1b9', @gateway.send(:signature, 'cc_debit', {
+ 'UserName' => 'user',
+ 'Timestamp' => '2013-10-08T14:31:54.Z',
+ 'RequestID' => 'wouykiikdvqbwwxueppby',
+ 'PymtType' => 'cc_debit'
+ }, {
+ 'Amount' => 100,
+ 'Currency' => 'USD',
+ 'TrackingNumber' => '123456789'
+ })
+ end
+
+ def test_signature_for_cc_refund_action
+ assert_equal '9b174f1ebf5763e4793a52027645ff5156fca2e3', @gateway.send(:signature, 'cc_refund', {
+ 'UserName' => 'user',
+ 'Timestamp' => '2013-10-08T14:31:54.Z',
+ 'RequestID' => 'wouykiikdvqbwwxueppby',
+ 'PymtType' => 'cc_refund'
+ }, {
+ 'Amount' => 100,
+ 'Currency' => 'USD',
+ 'TrackingNumber' => '123456789'
+ })
+ end
+
+ def test_signature_for_void_action
+ assert_equal '236d4a857ee2e8cfec851be250159367d2c7c52e', @gateway.send(:signature, 'void', {
+ 'UserName' => 'user',
+ 'Timestamp' => '2013-10-08T14:31:54.Z',
+ 'RequestID' => 'wouykiikdvqbwwxueppby'
+ }, {
+ 'Amount' => 100,
+ 'Currency' => 'USD',
+ 'TrackingNumber' => '123456789'
+ })
+ end
+
+ def test_expdate
+ @credit_card.year = 2015
+ @credit_card.month = 9
+ assert_equal "0915", @gateway.send(:expdate, @credit_card)
+ end
+
+ private
+
+ def failed_void_response
+ %w(
+ ApprovalCode=
+ ErrorCode=error:canNotBeVoided
+ Message=Error+processing+transaction+because+the+payment+may+not+be+voided
+ RequestNumber=603758541
+ RequestResult=ok
+ Status=Approved
+ TrackingNumber=123456789
+ ).join('&')
+ end
+
+ def successful_authorization_response
+ %w(
+ ApprovalCode=123456
+ ErrorCode=
+ Message=
+ RequestNumber=603758541
+ RequestResult=ok
+ Status=Approved
+ TrackingNumber=123456789
+ ).join('&')
+ end
+
+ def successful_purchase_response
+ %w(
+ ApprovalCode=123456
+ ErrorCode=
+ Message=
+ RequestNumber=603758541
+ RequestResult=ok
+ Status=Approved
+ TrackingNumber=123456789
+ ).join('&')
+ end
+
+ def successful_capture_response
+ %w(
+ ApprovalCode=123456
+ ErrorCode=
+ Message=
+ RequestNumber=603758541
+ RequestResult=ok
+ Status=Approved
+ TrackingNumber=123456789
+ ).join('&')
+ end
+
+ def invalid_preauth_number_response
+ %w(
+ ApprovalCode=
+ ErrorCode=invalid:PreAuthNumber
+ Message=Error+processing+transaction+because+the+pre-auth+number
+ RequestNumber=603758541
+ RequestResult=ok
+ Status=Invalid:PreauthNumber
+ TrackingNumber=123456789
+ ).join('&')
+ end
+
+ def insufficient_preauth_amount_response
+ %w(
+ ApprovalCode=
+ ErrorCode=rejected:PreauthAmountInsufficient
+ Message=Invalid+because+the+preauthorization+amount+100+is+insufficient
+ RequestNumber=603758541
+ RequestResult=ok
+ Status=Rejected:PreauthAmountInsufficient
+ TrackingNumber=123456789
+ ).join('&')
+ end
+
+ def invalid_credit_card_response
+ %w(
+ ApprovalCode=
+ ErrorCode=invalid:cardNumber
+ Message=Error+processing+transaction+because+CardNumber+is+not+between+12+and+19+in+length
+ RequestNumber=603758541
+ RequestResult=ok
+ Status=Invalid:CardNumber
+ TrackingNumber=123456789
+ ).join('&')
+ end
+
+ def expired_credit_card_response
+ %w(
+ ApprovalCode=
+ ErrorCode=invalid:CustomerCardExpiryDate
+ Message=Invalid+because+the+card+expiry+date+is+not+a+date+in+the+future
+ RequestNumber=603758541
+ RequestResult=ok
+ Status=Invalid:CustomerCardExpiryDate
+ TrackingNumber=123456789
+ ).join('&')
+ end
+
+ def declined_purchese_response
+ %w(
+ ApprovalCode=123456
+ ErrorCode=
+ Message=
+ RequestNumber=603758541
+ RequestResult=ok
+ Status=Declined
+ TrackingNumber=123456789
+ ).join('&')
+ end
+
+ def successful_refund_response
+ %w(
+ ApprovalCode=123456
+ ErrorCode=
+ Message=
+ RequestNumber=603758541
+ RequestResult=ok
+ Status=Approved
+ TrackingNumber=123456789
+ ).join('&')
+ end
+
+ def amount_greater_than_original_amount_refund_response
+ %w(
+ ApprovalCode=
+ ErrorCode=invalid:RefundAmountGreaterThanOriginalAmount
+ Message=Invalid+because+the+payment+amount+cannot+be+greater+than+the+original+charge
+ RequestNumber=603758541
+ RequestResult=ok
+ Status=Invalid:RefundAmountGreaterThanOriginalAmount
+ TrackingNumber=123456789
+ ).join('&')
+ end
+
+ def successful_void_response
+ %w(
+ ApprovalCode=123456
+ ErrorCode=
+ Message=
+ RequestNumber=603758541
+ RequestResult=ok
+ Status=Voided
+ TrackingNumber=123456789
+ ).join('&')
+ end
+end
diff --git a/test/unit/gateways/payex_test.rb b/test/unit/gateways/payex_test.rb
new file mode 100644
index 00000000000..b2e5a8a78ef
--- /dev/null
+++ b/test/unit/gateways/payex_test.rb
@@ -0,0 +1,284 @@
+require 'test_helper'
+
+class PayexTest < Test::Unit::TestCase
+ def setup
+ @gateway = PayexGateway.new(
+ :account => 'account',
+ :encryption_key => 'encryption_key'
+ )
+
+ @credit_card = credit_card
+ @amount = 1000
+
+ @options = {
+ :order_id => '1234',
+ }
+ end
+
+ def test_successful_purchase
+ @gateway.expects(:ssl_post).times(2).returns(successful_initialize_response, successful_purchase_response)
+
+ assert response = @gateway.purchase(@amount, @credit_card, @options)
+ assert_instance_of MultiResponse, response
+ assert_success response
+
+ assert_equal '2623681', response.authorization
+ assert response.test?
+ end
+
+ def test_failed_purchase
+ @gateway.expects(:ssl_post).times(2).returns(successful_initialize_response, failed_purchase_response)
+
+ assert response = @gateway.purchase(@amount, @credit_card, @options)
+ assert_failure response
+ assert response.test?
+ end
+
+ def test_successful_authorize
+ @gateway.expects(:ssl_post).times(2).returns(successful_initialize_response, successful_authorize_response)
+ assert response = @gateway.authorize(@amount, @credit_card, @options)
+ assert_success response
+ assert response.authorization
+ assert_equal 'OK', response.message
+ assert_equal '2624653', response.authorization
+ assert response.test?
+ end
+
+ def test_successful_capture
+ @gateway.expects(:ssl_post).returns(successful_capture_response)
+ assert response = @gateway.capture(@amount, 'fakeauth')
+ assert_success response
+ assert_equal '2624655', response.authorization
+ assert response.test?
+ end
+
+ def test_failed_capture
+ @gateway.expects(:ssl_post).returns(failed_capture_response)
+ assert response = @gateway.capture(@amount, '1')
+ assert_failure response
+ assert_not_equal 'OK', response.message
+ assert_not_equal 'RecordNotFound', response.params[:status_errorcode]
+ assert response.test?
+ end
+
+ def test_successful_void
+ @gateway.expects(:ssl_post).returns(successful_void_response)
+
+ assert response = @gateway.void('fakeauth')
+ assert_success response
+ assert_equal '2624825', response.authorization
+ assert response.test?
+ end
+
+ def test_unsuccessful_void
+ @gateway.expects(:ssl_post).returns(unsuccessful_void_response)
+ assert response = @gateway.void("1")
+ assert_failure response
+ assert_not_equal 'OK', response.message
+ assert_match /1/, response.message
+ assert response.test?
+ end
+
+ def test_successful_refund
+ @gateway.expects(:ssl_post).returns(successful_refund_response)
+ assert response = @gateway.refund(@amount - 200, 'fakeauth', order_id: '123')
+ assert_success response
+ assert_equal '2624828', response.authorization
+ assert response.test?
+ end
+
+ def test_unsuccessful_refund
+ @gateway.expects(:ssl_post).returns(unsuccessful_refund_response)
+ assert response = @gateway.refund(@amount, "1", order_id: '123')
+ assert_failure response
+ assert_not_equal 'OK', response.message
+ assert_match /1/, response.message
+ assert response.test?
+ end
+
+ def test_successful_store
+ @gateway.expects(:ssl_post).times(3).returns(successful_store_response, successful_initialize_response, successful_purchase_response)
+ assert response = @gateway.store(@credit_card, @options.merge({merchant_ref: '9876'}))
+ assert_success response
+ assert_equal 'OK', response.message
+ assert_equal 'bcea4ac8d1f44640bff7a8c93caa249c', response.authorization
+ assert response.test?
+ end
+
+ def test_successful_unstore
+ @gateway.expects(:ssl_post).returns(successful_unstore_response)
+ assert response = @gateway.unstore('fakeauth')
+ assert_success response
+ assert_equal 'OK', response.message
+ assert response.test?
+ end
+
+ def test_successful_purchase_with_stored_card
+ @gateway.expects(:ssl_post).returns(successful_autopay_response)
+ assert response = @gateway.purchase(@amount, 'fakeauth', @options.merge({order_id: '5678'}))
+ assert_success response
+ assert_equal 'OK', response.message
+ assert_equal '2624657', response.authorization
+ assert response.test?
+ end
+
+ private
+
+ def successful_initialize_response
+ %q{
+
+
+
+ <?xml version="1.0" encoding="utf-8" ?><payex><header name="Payex Header v1.0"><id>09ef982cf2584d58bf4363dacd2ef127</id><date>2013-11-06 14:19:23</date></header><status><code>OK</code><description>OK</description><errorCode>OK</errorCode><paramName /><thirdPartyError /><thirdPartySubError /></status><orderRef>53681e74064a4621b93a6fcceba20c00</orderRef><sessionRef>7424a69d355c4cafa853ff49553b786f</sessionRef><redirectUrl>https://test-confined.payex.com/PxOrderCC.aspx?orderRef=53681e74064a4621b93a6fcceba20c00</redirectUrl></payex>
+
+
+
+ }
+ end
+
+ # Place raw successful response from gateway here
+ def successful_purchase_response
+ %q{
+
+
+
+ <?xml version="1.0" encoding="utf-8" ?><payex><header name="Payex Header v1.0"><id>45eca449c8b54b54ac8811d4c26f638d</id><date>2013-11-06 14:19:35</date></header><status><code>OK</code><description>OK</description><errorCode>OK</errorCode><paramName /><thirdPartyError /></status><transactionStatus>0</transactionStatus><transactionRef>750dc1438350481086abd0438bde0c23</transactionRef><transactionNumber>2623681</transactionNumber><orderId>1234</orderId><productId>4321</productId><paymentMethod>VISA</paymentMethod><productNumber>4321</productNumber><BankHash>00000001-4581-0903-5682-000000000000</BankHash><AuthenticatedStatus>None</AuthenticatedStatus><AuthenticatedWith>N</AuthenticatedWith></payex>
+
+
+
+ }
+ end
+
+ def failed_purchase_response
+ %q{
+
+
+
+ <?xml version="1.0" encoding="utf-8" ?><payex><header name="Payex Header v1.0"><id>131faa4301f74e91bf29e9749ad8f2a6</id><date>2013-11-06 14:40:18</date></header><status><code>ValidationError_InvalidParameter</code><errorCode>ValidationError_InvalidParameter</errorCode><description>Invalid parameter:expireDate
+ Parameter name: expireDate</description><paramName>expireDate</paramName><thirdPartyError /></status></payex>
+
+
+
+ }
+ end
+
+ def successful_authorize_response
+ %q{
+
+
+
+ <?xml version="1.0" encoding="utf-8" ?><payex><header name="Payex Header v1.0"><id>41ebf6488fdb42a79baf49d2ef9e7dc6</id><date>2013-11-06 14:43:01</date></header><status><code>OK</code><description>OK</description><errorCode>OK</errorCode><paramName /><thirdPartyError /></status><transactionStatus>3</transactionStatus><transactionRef>89cbf30161f442228cbca16ff7f886d4</transactionRef><transactionNumber>2624653</transactionNumber><orderId>1234</orderId><productId>4321</productId><paymentMethod>VISA</paymentMethod><productNumber>4321</productNumber><BankHash>00000001-4581-0903-5682-000000000000</BankHash><AuthenticatedStatus>None</AuthenticatedStatus><AuthenticatedWith>N</AuthenticatedWith></payex>
+
+
+
+ }
+ end
+
+ def successful_capture_response
+ %q{
+
+
+
+ <?xml version="1.0" encoding="utf-8" ?><payex><header name="Payex Header v1.0"><id>efe1a4572c9b4ed5a656d648bf7f9207</id><date>2013-11-06 14:43:03</date></header><status><code>OK</code><description>OK</description><errorCode>OK</errorCode><paramName /><thirdPartyError /><thirdPartySubError /></status><transactionStatus>6</transactionStatus><transactionNumber>2624655</transactionNumber><originalTransactionNumber>2624653</originalTransactionNumber></payex>
+
+
+
+ }
+ end
+
+ def failed_capture_response
+ %q{
+
+
+
+ <?xml version="1.0" encoding="utf-8" ?><payex><header name="Payex Header v1.0"><id>19706b063aad458aa9783563a4e5bbff</id><date>2013-11-06 14:53:34</date></header><status><code>ValidationError_Generic</code><description>1</description><errorCode>NoRecordFound</errorCode><paramName /><thirdPartyError /><thirdPartySubError /></status></payex>
+
+
+
+ }
+ end
+
+ def successful_void_response
+ %q{
+
+
+
+ <?xml version="1.0" encoding="utf-8" ?><payex><header name="Payex Header v1.0"><id>219b3a4b4ae0478482c75eba06d5a0dd</id><date>2013-11-06 14:56:48</date></header><status><code>OK</code><description>OK</description><errorCode>OK</errorCode><paramName /><thirdPartyError /><thirdPartySubError /></status><transactionStatus>4</transactionStatus><transactionNumber>2624825</transactionNumber><originalTransactionNumber>2624824</originalTransactionNumber></payex>
+
+
+
+ }
+ end
+
+ def unsuccessful_void_response
+ %q{
+
+
+
+ <?xml version="1.0" encoding="utf-8" ?><payex><header name="Payex Header v1.0"><id>220b395b966a43eb9d0c70109f6dadd3</id><date>2013-11-06 15:02:24</date></header><status><code>ValidationError_Generic</code><description>1</description><errorCode>Error_Generic</errorCode><paramName /><thirdPartyError /><thirdPartySubError /></status></payex>
+
+
+
+ }
+ end
+
+ def successful_refund_response
+ %q{
+
+
+
+ <?xml version="1.0" encoding="utf-8" ?><payex><header name="Payex Header v1.0"><id>a1e70daf3ed842ddb72e58a28f5cbc11</id><date>2013-11-06 14:57:54</date></header><status><code>OK</code><description>OK</description><errorCode>OK</errorCode><paramName /><thirdPartyError /><thirdPartySubError /></status><transactionStatus>2</transactionStatus><transactionNumber>2624828</transactionNumber><originalTransactionNumber>2624827</originalTransactionNumber></payex>
+
+
+
+ }
+ end
+
+ def unsuccessful_refund_response
+ %q{
+
+
+
+ <?xml version="1.0" encoding="utf-8" ?><payex><header name="Payex Header v1.0"><id>e82613f6c59d4e08a7163cd91c2b3ce5</id><date>2013-11-06 15:02:23</date></header><status><code>ValidationError_Generic</code><description>1</description><errorCode>Error_Generic</errorCode><paramName /><thirdPartyError /><thirdPartySubError /></status></payex>
+
+
+
+ }
+ end
+
+ def successful_store_response
+ %q{
+
+
+
+ <?xml version="1.0" encoding="utf-8" ?><payex><header name="Payex Header v1.0"><id>3c8063b7fcb64a449b715fe711f0a03f</id><date>2013-11-06 14:43:04</date></header><status><code>OK</code><description>OK</description><errorCode>OK</errorCode><paramName /><thirdPartyError /><thirdPartySubError /></status><agreementRef>bcea4ac8d1f44640bff7a8c93caa249c</agreementRef></payex>
+
+
+
+ }
+ end
+
+ def successful_unstore_response
+ %q{
+
+
+
+ <?xml version="1.0" encoding="utf-8" ?><payex><header name="Payex Header v1.0"><id>7935ca4c24c3467cb36c48a270557194</id><date>2013-11-06 15:06:54</date></header><status><code>OK</code><description>OK</description><errorCode>OK</errorCode><paramName /><thirdPartyError /><thirdPartySubError /></status><agreementRef>7e9c6342dc20459691d1abb027a3c8c0</agreementRef></payex>
+
+
+
+ }
+ end
+
+ def successful_autopay_response
+ %q{
+
+
+
+ <?xml version="1.0" encoding="utf-8" ?><payex><header name="Payex Header v1.0"><id>37a7164c16804af199b7d6aade0aa580</id><date>2013-11-06 14:43:09</date></header><status><code>OK</code><description>OK</description><errorCode>OK</errorCode><paramName /><thirdPartyError /><thirdPartySubError /></status><transactionStatus>3</transactionStatus><transactionRef>de2984e302da40b498afe5aced8cea7e</transactionRef><transactionNumber>2624657</transactionNumber><paymentMethod>VISA</paymentMethod><captureTokens><stan>1337</stan><terminalId>666</terminalId><transactionTime>11/6/2013 2:43:09 PM</transactionTime></captureTokens><pending>false</pending></payex>
+
+
+
+ }
+ end
+end
diff --git a/test/unit/gateways/payflow_test.rb b/test/unit/gateways/payflow_test.rb
index 9ee933154d0..685da48bd49 100644
--- a/test/unit/gateways/payflow_test.rb
+++ b/test/unit/gateways/payflow_test.rb
@@ -12,6 +12,7 @@ def setup
@amount = 100
@credit_card = credit_card('4242424242424242')
@options = { :billing_address => address.merge(:first_name => "Longbob", :last_name => "Longsen") }
+ @check = check( :name => 'Jim Smith' )
end
def test_successful_authorization
@@ -78,6 +79,18 @@ def test_cvv_result
assert_equal 'M', response.cvv_result['code']
end
+ def test_ach_purchase
+ @gateway.expects(:ssl_post).with(anything, regexp_matches(/#{@check.account_number}<\//), anything).returns("")
+ @gateway.expects(:parse).returns({})
+ @gateway.purchase(@amount, @check)
+ end
+
+ def test_ach_credit
+ @gateway.expects(:ssl_post).with(anything, regexp_matches(/#{@check.account_number}<\//), anything).returns("")
+ @gateway.expects(:parse).returns({})
+ @gateway.credit(@amount, @check)
+ end
+
def test_using_test_mode
assert @gateway.test?
end
diff --git a/test/unit/gateways/paymill_test.rb b/test/unit/gateways/paymill_test.rb
index 5417a0016e4..9c311960c7c 100644
--- a/test/unit/gateways/paymill_test.rb
+++ b/test/unit/gateways/paymill_test.rb
@@ -14,7 +14,7 @@ def test_successful_purchase
assert response = @gateway.purchase(@amount, @credit_card)
assert_success response
assert_equal "tran_c94ba7df2dae8fd55028df41173c;", response.authorization
- assert_equal "Transaction approved", response.message
+ assert_equal "General success response.", response.message
assert_equal 20000, response.params['data']['response_code']
assert_equal 'pay_b8e6a28fc5e5e1601cdbefbaeb8a', response.params['data']['payment']['id']
assert_equal '5100', response.params['data']['payment']['last4']
@@ -23,7 +23,7 @@ def test_successful_purchase
assert response.test?
end
- def test_failed_purchase_with_invalid_credit_card
+ def test_failed_store_card_attempting_purchase
@gateway.expects(:raw_ssl_request).returns(failed_store_response)
response = @gateway.purchase(@amount, @credit_card)
assert_failure response
@@ -31,6 +31,14 @@ def test_failed_purchase_with_invalid_credit_card
assert_equal '000.100.201', response.params['transaction']['processing']['return']['code']
end
+ def test_failed_purchase
+ @gateway.stubs(:raw_ssl_request).returns(successful_store_response, failed_purchase_response)
+ response = @gateway.purchase(@amount, @credit_card)
+ assert_failure response
+ assert_equal 'Card declined by authorization system.', response.message
+ assert_equal 50102, response.params['data']['response_code']
+ end
+
def test_invalid_login
@gateway.stubs(:raw_ssl_request).returns(successful_store_response, failed_login_response)
response = @gateway.purchase(@amount, @credit_card)
@@ -52,10 +60,10 @@ def test_successful_authorize_and_capture
assert_success response
assert response.test?
- assert_equal "tran_50fb13e10636cf1e59e13018d100;preauth_57c0c87ae3d193f66dc8", response.authorization
- assert_equal "Transaction approved", response.message
- assert_equal '5100', response.params['data']['payment']['last4']
- assert_equal 10001, response.params['data']['response_code']
+ assert_equal "tran_4c612d5293e26d56d986eb89648c;preauth_fdf916cab73b97c4a139", response.authorization
+ assert_equal "General success response.", response.message
+ assert_equal '0004', response.params['data']['payment']['last4']
+ assert_equal 20000, response.params['data']['response_code']
assert_nil response.avs_result["message"]
assert_nil response.cvv_result["message"]
@@ -64,7 +72,15 @@ def test_successful_authorize_and_capture
assert_success response
assert response.test?
assert_equal 20000, response.params['data']['response_code']
- assert_equal "Transaction approved", response.message
+ assert_equal "General success response.", response.message
+ end
+
+ def test_failed_authorize
+ @gateway.stubs(:raw_ssl_request).returns(successful_store_response, failed_authorize_response)
+ response = @gateway.authorize(@amount, @credit_card)
+ assert_failure response
+ assert_equal 'Card declined by authorization system.', response.message
+ assert_equal 50102, response.params['data']['response_code']
end
def test_successful_authorize_and_void
@@ -77,7 +93,7 @@ def test_successful_authorize_and_void
response = @gateway.void(response.authorization)
assert_success response
assert response.test?
- assert_equal "Transaction approved", response.message
+ assert_equal "Transaction approved.", response.message
end
def test_failed_capture
@@ -101,7 +117,7 @@ def test_successful_refund
assert_success refund
assert response.test?
- assert_equal 'Transaction approved', refund.message
+ assert_equal 'General success response.', refund.message
assert_equal 'tran_89c8728e94273510afa99ab64e45', refund.params['data']['transaction']['id']
assert_equal 'refund_d02807f46181c0919016;', refund.authorization
assert_equal 20000, refund.params['data']['response_code']
@@ -142,7 +158,7 @@ def test_successful_purchase_with_token
assert response = @gateway.purchase(@amount, "token")
assert_success response
assert_equal "tran_c94ba7df2dae8fd55028df41173c;", response.authorization
- assert_equal "Transaction approved", response.message
+ assert_equal "General success response.", response.message
assert_equal 20000, response.params['data']['response_code']
assert_equal 'pay_b8e6a28fc5e5e1601cdbefbaeb8a', response.params['data']['payment']['id']
assert_equal '5100', response.params['data']['payment']['last4']
@@ -158,10 +174,10 @@ def test_successful_authorize_with_token
assert_success response
assert response.test?
- assert_equal "tran_50fb13e10636cf1e59e13018d100;preauth_57c0c87ae3d193f66dc8", response.authorization
- assert_equal "Transaction approved", response.message
- assert_equal '5100', response.params['data']['payment']['last4']
- assert_equal 10001, response.params['data']['response_code']
+ assert_equal "tran_4c612d5293e26d56d986eb89648c;preauth_fdf916cab73b97c4a139", response.authorization
+ assert_equal "General success response.", response.message
+ assert_equal '0004', response.params['data']['payment']['last4']
+ assert_equal 20000, response.params['data']['response_code']
assert_nil response.avs_result["message"]
assert_nil response.cvv_result["message"]
end
@@ -232,81 +248,244 @@ def successful_purchase_response
JSON
end
+ def failed_purchase_response
+ MockResponse.failed <<-JSON
+ {
+ "data":{
+ "id":"tran_a432ce3b113cdd65b48e0d05db88",
+ "amount":"100",
+ "origin_amount":100,
+ "status":"failed",
+ "description":null,
+ "livemode":false,
+ "refunds":null,
+ "currency":"EUR",
+ "created_at":1385054845,
+ "updated_at":1385054845,
+ "response_code":50102,
+ "short_id":null,
+ "is_fraud":false,
+ "invoices":[
+
+ ],
+ "app_id":null,
+ "fees":[
+
+ ],
+ "payment":{
+ "id":"pay_8b75b960574031979a880f98",
+ "type":"creditcard",
+ "client":"client_a69d8452d530ed20b297",
+ "card_type":"mastercard",
+ "country":null,
+ "expire_month":"5",
+ "expire_year":"2020",
+ "card_holder":"",
+ "last4":"5100",
+ "created_at":1385054844,
+ "updated_at":1385054845,
+ "app_id":null
+ },
+ "client":{
+ "id":"client_a69d8452d530ed20b297",
+ "email":null,
+ "description":null,
+ "created_at":1385054845,
+ "updated_at":1385054845,
+ "app_id":null,
+ "payment":[
+
+ ],
+ "subscription":null
+ },
+ "preauthorization":null
+ },
+ "mode":"test"
+ }
+ JSON
+ end
+
def successful_authorize_response
MockResponse.succeeded <<-JSON
- { "data":{
- "id":"tran_50fb13e10636cf1e59e13018d100",
- "amount":"100",
- "origin_amount":100,
- "status":"preauth",
- "description":null,
- "livemode":false,
- "refunds":null,
- "currency":"EUR",
- "created_at":1360787311,
- "updated_at":1360787311,
- "response_code":10001,
- "invoices":[
-
- ],
- "payment":{
- "id":"pay_58e0662ef367027b2356f263e5aa",
- "type":"creditcard",
- "client":"client_9e4b7b0d61adc9a9e64e",
- "card_type":"mastercard",
- "country":null,
- "expire_month":9,
- "expire_year":2014,
- "card_holder":null,
- "last4":"5100",
- "created_at":1360787310,
- "updated_at":1360787311
- },
- "client":{
- "id":"client_9e4b7b0d61adc9a9e64e",
- "email":null,
- "description":null,
- "created_at":1360787311,
- "updated_at":1360787311,
- "payment":[
+ {
+ "data":{
+ "id":"tran_4c612d5293e26d56d986eb89648c",
+ "amount":"100",
+ "origin_amount":100,
+ "status":"preauth",
+ "description":null,
+ "livemode":false,
+ "refunds":null,
+ "currency":"EUR",
+ "created_at":1385054035,
+ "updated_at":1385054035,
+ "response_code":20000,
+ "short_id":"7357.7357.7357",
+ "is_fraud":false,
+ "invoices":[
- ],
- "subscription":null
+ ],
+ "app_id":null,
+ "fees":[
+
+ ],
+ "payment":{
+ "id":"pay_f9ff269434185e0789106758",
+ "type":"creditcard",
+ "client":"client_d5179e1b6a8f596b19b9",
+ "card_type":"mastercard",
+ "country":null,
+ "expire_month":"9",
+ "expire_year":"2014",
+ "card_holder":"",
+ "last4":"0004",
+ "created_at":1385054033,
+ "updated_at":1385054035,
+ "app_id":null
+ },
+ "client":{
+ "id":"client_d5179e1b6a8f596b19b9",
+ "email":null,
+ "description":null,
+ "created_at":1385054035,
+ "updated_at":1385054035,
+ "app_id":null,
+ "payment":[
+
+ ],
+ "subscription":null
+ },
+ "preauthorization":{
+ "id":"preauth_fdf916cab73b97c4a139",
+ "amount":"100",
+ "currency":"EUR",
+ "status":"closed",
+ "livemode":false,
+ "created_at":1385054035,
+ "updated_at":1385054035,
+ "app_id":null,
+ "payment":{
+ "id":"pay_f9ff269434185e0789106758",
+ "type":"creditcard",
+ "client":"client_d5179e1b6a8f596b19b9",
+ "card_type":"mastercard",
+ "country":null,
+ "expire_month":"9",
+ "expire_year":"2014",
+ "card_holder":"",
+ "last4":"0004",
+ "created_at":1385054033,
+ "updated_at":1385054035,
+ "app_id":null
+ },
+ "client":{
+ "id":"client_d5179e1b6a8f596b19b9",
+ "email":null,
+ "description":null,
+ "created_at":1385054035,
+ "updated_at":1385054035,
+ "app_id":null,
+ "payment":[
+
+ ],
+ "subscription":null
+ }
+ }
},
- "preauthorization":{
- "id":"preauth_57c0c87ae3d193f66dc8",
+ "mode":"test"
+ }
+ JSON
+ end
+
+ # Paymill returns an HTTP Status code of 200 for an auth failure.
+ def failed_authorize_response
+ MockResponse.succeeded <<-JSON
+ {
+ "data":{
+ "id":"tran_e53189278c7250bfa15c9c580ff2",
"amount":"100",
- "status":"closed",
+ "origin_amount":100,
+ "status":"failed",
+ "description":null,
"livemode":false,
- "created_at":1360787311,
- "updated_at":1360787311,
+ "refunds":null,
+ "currency":"EUR",
+ "created_at":1385054501,
+ "updated_at":1385054501,
+ "response_code":50102,
+ "short_id":null,
+ "is_fraud":false,
+ "invoices":[
+
+ ],
+ "app_id":null,
+ "fees":[
+
+ ],
"payment":{
- "id":"pay_58e0662ef367027b2356f263e5aa",
+ "id":"pay_7bc2d73764f38040df934995",
"type":"creditcard",
- "client":"client_9e4b7b0d61adc9a9e64e",
+ "client":"client_531e6247ff900e734884",
"card_type":"mastercard",
"country":null,
- "expire_month":9,
- "expire_year":2014,
- "card_holder":null,
+ "expire_month":"5",
+ "expire_year":"2020",
+ "card_holder":"",
"last4":"5100",
- "created_at":1360787310,
- "updated_at":1360787311
- },
- "client":{
- "id":"client_9e4b7b0d61adc9a9e64e",
+ "created_at":1385054500,
+ "updated_at":1385054501,
+ "app_id":null
+ },
+ "client":{
+ "id":"client_531e6247ff900e734884",
"email":null,
"description":null,
- "created_at":1360787311,
- "updated_at":1360787311,
+ "created_at":1385054501,
+ "updated_at":1385054501,
+ "app_id":null,
"payment":[
],
"subscription":null
+ },
+ "preauthorization":{
+ "id":"preauth_cfa6a29b4c679efee58b",
+ "amount":"100",
+ "currency":"EUR",
+ "status":"failed",
+ "livemode":false,
+ "created_at":1385054501,
+ "updated_at":1385054501,
+ "app_id":null,
+ "payment":{
+ "id":"pay_7bc2d73764f38040df934995",
+ "type":"creditcard",
+ "client":"client_531e6247ff900e734884",
+ "card_type":"mastercard",
+ "country":null,
+ "expire_month":"5",
+ "expire_year":"2020",
+ "card_holder":"",
+ "last4":"5100",
+ "created_at":1385054500,
+ "updated_at":1385054501,
+ "app_id":null
+ },
+ "client":{
+ "id":"client_531e6247ff900e734884",
+ "email":null,
+ "description":null,
+ "created_at":1385054501,
+ "updated_at":1385054501,
+ "app_id":null,
+ "payment":[
+
+ ],
+ "subscription":null
+ }
}
- }
- },
- "mode":"test"
+ },
+ "mode":"test"
}
JSON
end
diff --git a/test/unit/gateways/payscout_test.rb b/test/unit/gateways/payscout_test.rb
new file mode 100644
index 00000000000..0781da14568
--- /dev/null
+++ b/test/unit/gateways/payscout_test.rb
@@ -0,0 +1,538 @@
+require 'test_helper'
+
+class PayscoutTest < Test::Unit::TestCase
+ def setup
+ @gateway = PayscoutGateway.new(
+ :username => 'xxx',
+ :password => 'xxx'
+ )
+
+ @credit_card = credit_card
+ @amount = 100
+
+ @options = {
+ :order_id => '1',
+ :billing_address => address,
+ :description => 'Store Purchase'
+ }
+ end
+
+ # Purchase
+
+ def test_approved_puschase
+ @gateway.expects(:ssl_post).returns(approved_purchase_response)
+
+ assert response = @gateway.purchase(@amount, @credit_card, @options)
+ assert_instance_of Response, response
+ assert_success response
+
+ assert_equal '1234567891', response.authorization
+ assert_equal 'The transaction has been approved', response.message
+ assert response.test?
+ end
+
+ def test_declined_puschase
+ @gateway.expects(:ssl_post).returns(declined_purchase_response)
+
+ assert response = @gateway.purchase(@amount, @credit_card, @options)
+ assert_instance_of Response, response
+ assert_failure response
+
+ assert_equal '1234567892', response.authorization
+ assert_equal 'The transaction has been declined', response.message
+ assert response.test?
+ end
+
+ # Authorization
+
+ def test_approved_authorization
+ @gateway.expects(:ssl_post).returns(approved_authorization_response)
+
+ assert response = @gateway.authorize(@amount, @credit_card, @options)
+ assert_instance_of Response, response
+ assert_success response
+
+ assert_equal '1234567890', response.authorization
+ assert_equal 'The transaction has been approved', response.message
+ assert response.test?
+ end
+
+ def test_declined_authorization
+ @gateway.expects(:ssl_post).returns(declined_authorization_response)
+
+ assert response = @gateway.authorize(@amount, @credit_card, @options)
+ assert_instance_of Response, response
+ assert_failure response
+
+ assert_equal '1234567893', response.authorization
+ assert_equal 'The transaction has been declined', response.message
+ assert response.test?
+ end
+
+ # Capture
+
+ def test_approved_capture
+ @gateway.expects(:ssl_post).returns(approved_capture_response)
+
+ assert response = @gateway.capture(@amount, '1234567894', @options)
+ assert_instance_of Response, response
+ assert_success response
+
+ assert_equal '1234567894', response.authorization
+ assert_equal 'The transaction has been approved', response.message
+ assert response.test?
+ end
+
+ def test_invalid_amount_capture
+ @gateway.expects(:ssl_post).returns(invalid_amount_capture_response)
+
+ assert response = @gateway.capture(@amount, '1234567895', @options)
+ assert_instance_of Response, response
+ assert_failure response
+
+ assert_equal '1234567895', response.authorization
+ assert_equal 'The+specified+amount+of+2.00+exceeds+the+authorization+amount+of+1.00', response.message
+ assert response.test?
+ end
+
+ def test_not_found_transaction_id_capture
+ @gateway.expects(:ssl_post).returns(not_found_transaction_id_capture_response)
+
+ assert capture = @gateway.capture(@amount, '1234567890')
+ assert_failure capture
+ assert_match 'Transaction+not+found', capture.message
+ end
+
+ def test_invalid_transaction_id_capture
+ @gateway.expects(:ssl_post).returns(invalid_transaction_id_capture_response)
+
+ assert capture = @gateway.capture(@amount, '')
+ assert_failure capture
+ assert_match 'Invalid+Transaction+ID', capture.message
+ end
+
+ # Refund
+
+ def test_approved_refund
+ @gateway.expects(:ssl_post).returns(approved_refund_response)
+
+ assert refund = @gateway.refund(@amount, '1234567890')
+ assert_success refund
+ assert_equal "The transaction has been approved", refund.message
+ end
+
+ def test_not_found_transaction_id_refund
+ @gateway.expects(:ssl_post).returns(not_found_transaction_id_refund_response)
+
+ assert refund = @gateway.refund(@amount, '1234567890')
+ assert_failure refund
+ assert_match "Transaction+not+found", refund.message
+ end
+
+ def test_invalid_transaction_id_refund
+ @gateway.expects(:ssl_post).returns(invalid_transaction_id_refund_response)
+
+ assert refund = @gateway.refund(@amount, '')
+ assert_failure refund
+ assert_match "Invalid+Transaction+ID", refund.message
+ end
+
+ def test_invalid_amount_refund
+ @gateway.expects(:ssl_post).returns(invalid_amount_refund_response)
+
+ assert refund = @gateway.refund(200, '1234567890')
+ assert_failure refund
+ assert_match "Refund+amount+may+not+exceed+the+transaction+balance", refund.message
+ end
+
+ # Void
+
+ def test_approved_void_purchase
+ @gateway.expects(:ssl_post).returns(approved_void_purchase_response)
+
+ assert void = @gateway.void('1234567890')
+ assert_success void
+ assert_equal "The transaction has been approved", void.message
+ end
+
+ def test_approved_void_authorization
+ @gateway.expects(:ssl_post).returns(approved_void_authorization_response)
+
+ assert void = @gateway.void('1234567890')
+ assert_success void
+ assert_equal "The transaction has been approved", void.message
+ end
+
+ def test_invalid_transaction_id_void
+ @gateway.expects(:ssl_post).returns(invalid_transaction_id_void_response)
+
+ assert void = @gateway.void('')
+ assert_failure void
+ assert_match "Invalid+Transaction+ID", void.message
+ end
+
+ def test_not_found_transaction_id_void
+ @gateway.expects(:ssl_post).returns(not_found_transaction_id_void_response)
+
+ assert void = @gateway.void('1234567890')
+ assert_failure void
+ assert_match "Transaction+not+found", void.message
+ end
+
+ # Methods
+
+ def test_billing_address
+ post = {}
+ address = address(email: 'example@example.com')
+ @gateway.send(:add_address, post, { billing_address: address })
+
+ assert_equal address[:address1], post[:address1]
+ assert_equal address[:address2], post[:address2]
+ assert_equal address[:city], post[:city]
+ assert_equal address[:state], post[:state]
+ assert_equal address[:zip], post[:zip]
+ assert_equal address[:country], post[:country]
+ assert_equal address[:phone], post[:phone]
+ assert_equal address[:fax], post[:fax]
+ assert_equal address[:email], post[:email]
+ end
+
+ def test_shipping_address
+ post = {}
+ address = address(email: 'example@example.com', first_name: 'John', last_name: 'Doe')
+ @gateway.send(:add_address, post, { shipping_address: address })
+
+ assert_equal address[:first_name], post[:shipping_firstname]
+ assert_equal address[:last_name], post[:shipping_lastname]
+ assert_equal address[:company], post[:shipping_company]
+ assert_equal address[:address1], post[:shipping_address1]
+ assert_equal address[:address2], post[:shipping_address2]
+ assert_equal address[:city], post[:shipping_city]
+ assert_equal address[:country], post[:shipping_country]
+ assert_equal address[:state], post[:shipping_state]
+ assert_equal address[:zip], post[:shipping_zip]
+ assert_equal address[:email], post[:shipping_email]
+ end
+
+
+ def test_add_currency_from_options
+ post = {}
+ @gateway.send(:add_currency, post, 100, { currency: 'CAD' })
+
+ assert_equal 'CAD', post[:currency]
+ end
+
+ def test_add_currency_from_money
+ post = {}
+ @gateway.send(:add_currency, post, 100, {})
+
+ assert_equal 'USD', post[:currency]
+ end
+
+ def test_add_invoice
+ post = {}
+ options = {description: 'Order Description', order_id: '123'}
+ @gateway.send(:add_invoice, post, options)
+
+ assert_equal 'Order Description', post[:orderdescription]
+ assert_equal '123', post[:orderid]
+ end
+
+ def test_expdate
+ @credit_card = credit_card
+ @credit_card.year = 2015
+ @credit_card.month = 8
+
+ assert_equal "0815", @gateway.send(:expdate, @credit_card)
+ end
+
+ def test_add_creditcard
+ post = {}
+ @gateway.send(:add_creditcard, post, @credit_card)
+
+ assert_equal @credit_card.number, post[:ccnumber]
+ assert_equal @credit_card.verification_value, post[:cvv]
+ assert_equal @gateway.send(:expdate, @credit_card), post[:ccexp]
+ assert_equal @credit_card.first_name, post[:firstname]
+ assert_equal @credit_card.last_name, post[:lastname]
+ end
+
+ def test_parse
+ data = @gateway.send(:parse, approved_authorization_response)
+
+ assert data.keys.include?('response')
+ assert data.keys.include?('responsetext')
+ assert data.keys.include?('authcode')
+ assert data.keys.include?('transactionid')
+ assert data.keys.include?('avsresponse')
+ assert data.keys.include?('cvvresponse')
+ assert data.keys.include?('orderid')
+ assert data.keys.include?('type')
+ assert data.keys.include?('response_code')
+
+ assert_equal '1', data['response']
+ assert_equal 'SUCCESS', data['responsetext']
+ assert_equal '123456', data['authcode']
+ assert_equal '1234567890', data['transactionid']
+ assert_equal 'N', data['avsresponse']
+ assert_equal 'M', data['cvvresponse']
+ assert_equal '1', data['orderid']
+ assert_equal 'auth', data['type']
+ assert_equal '100', data['response_code']
+ end
+
+ def test_message_from_for_approved_response
+ assert_equal 'The transaction has been approved', @gateway.send(:message_from, {'response' => '1'})
+ end
+
+ def test_message_from_for_declined_response
+ assert_equal 'The transaction has been declined', @gateway.send(:message_from, {'response' => '2'})
+ end
+
+ def test_message_from_for_failed_response
+ assert_equal 'Error message', @gateway.send(:message_from, {'response' => '3', 'responsetext' => 'Error message'})
+ end
+
+ def test_success
+ assert @gateway.send(:success?, {'response' => '1'})
+ refute @gateway.send(:success?, {'response' => '2'})
+ refute @gateway.send(:success?, {'response' => '3'})
+ end
+
+ def test_post_data
+ parameters = {param1: 'value1', param2: 'value2'}
+ result = @gateway.send(:post_data, 'auth', parameters)
+
+ assert_match "username=xxx", result
+ assert_match "password=xxx", result
+ assert_match "type=auth", result
+ assert_match "param1=value1", result
+ assert_match "param2=value2", result
+ end
+
+ private
+
+ def approved_authorization_response
+ %w(
+ response=1
+ responsetext=SUCCESS
+ authcode=123456
+ transactionid=1234567890
+ avsresponse=N
+ cvvresponse=M
+ orderid=1
+ type=auth
+ response_code=100
+ ).join('&')
+ end
+
+ def declined_authorization_response
+ %w(
+ response=2
+ responsetext=DECLINE
+ authcode=
+ transactionid=1234567893
+ avsresponse=N
+ cvvresponse=M
+ orderid=1
+ type=auth
+ response_code=200
+ ).join('&')
+ end
+
+ def approved_purchase_response
+ %w(
+ response=1
+ responsetext=SUCCESS
+ authcode=123456
+ transactionid=1234567891
+ avsresponse=N
+ cvvresponse=M
+ orderid=1
+ type=sale
+ response_code=100
+ ).join('&')
+ end
+
+ def declined_purchase_response
+ %w(
+ response=2
+ responsetext=DECLINE
+ authcode=
+ transactionid=1234567892
+ avsresponse=N
+ cvvresponse=M
+ orderid=1
+ type=sale
+ response_code=200
+ ).join('&')
+ end
+
+ def approved_capture_response
+ %w(
+ response=1
+ responsetext=SUCCESS
+ authcode=123456
+ transactionid=1234567894
+ avsresponse=N
+ cvvresponse=M
+ orderid=1
+ type=capture
+ response_code=100
+ ).join('&')
+ end
+
+ def invalid_amount_capture_response
+ %w(
+ response=3
+ responsetext=The+specified+amount+of+2.00+exceeds+the+authorization+amount+of+1.00
+ authcode=
+ transactionid=1234567895
+ avsresponse=N
+ cvvresponse=M
+ orderid=1
+ type=capture
+ response_code=300
+ ).join('&')
+ end
+
+ def not_found_transaction_id_capture_response
+ %w(
+ response=3
+ responsetext=Transaction+not+found+REFID:4054576
+ authcode=
+ transactionid=
+ avsresponse=
+ cvvresponse=
+ orderid=1
+ type=capture
+ response_code=300
+ ).join('&')
+ end
+
+ def invalid_transaction_id_capture_response
+ %w(
+ response=3
+ responsetext=Invalid+Transaction+ID+/+Object+ID+specified:++REFID:4054567
+ authcode=
+ transactionid=
+ avsresponse=
+ cvvresponse=
+ orderid=1
+ type=capture
+ response_code=300
+ ).join('&')
+ end
+
+ def approved_refund_response
+ %w(
+ response=1
+ responsetext=SUCCESS
+ authcode=
+ transactionid=1234567896
+ avsresponse=
+ cvvresponse=
+ orderid=1
+ type=refund
+ response_code=100
+ ).join('&')
+ end
+
+ def not_found_transaction_id_refund_response
+ %w(
+ response=3
+ responsetext=Transaction+not+found+REFID:4054576
+ authcode=
+ transactionid=
+ avsresponse=
+ cvvresponse=
+ orderid=1
+ type=refund
+ response_code=300
+ ).join('&')
+ end
+
+ def invalid_transaction_id_refund_response
+ %w(
+ response=3
+ responsetext=Invalid+Transaction+ID+/+Object+ID+specified:++REFID:4054567
+ authcode=
+ transactionid=
+ avsresponse=
+ cvvresponse=
+ orderid=1
+ type=refund
+ response_code=300
+ ).join('&')
+ end
+
+ def invalid_amount_refund_response
+ %w(
+ response=3
+ responsetext=Refund+amount+may+not+exceed+the+transaction+balance+REFID:4054562
+ authcode=
+ transactionid=
+ avsresponse=
+ cvvresponse=
+ orderid=1
+ type=refund
+ response_code=300
+ ).join('&')
+ end
+
+ def approved_void_purchase_response
+ %w(
+ response=1
+ responsetext=Transaction+Void+Successful
+ authcode=123456
+ transactionid=1234567896
+ avsresponse=
+ cvvresponse=
+ orderid=1
+ type=void
+ response_code=100
+ ).join('&')
+ end
+
+ def approved_void_authorization_response
+ %w(
+ response=1
+ responsetext=Transaction+Void+Successful
+ authcode=123456
+ transactionid=1234567896
+ avsresponse=
+ cvvresponse=
+ orderid=1
+ type=void
+ response_code=100
+ ).join('&')
+ end
+
+ def invalid_transaction_id_void_response
+ %w(
+ response=3
+ responsetext=Invalid+Transaction+ID+/+Object+ID+specified:++REFID:4054572
+ authcode=
+ transactionid=
+ avsresponse=
+ cvvresponse=
+ orderid=1
+ type=void
+ response_code=300
+ ).join('&')
+ end
+
+ def not_found_transaction_id_void_response
+ %w(
+ response=3
+ responsetext=Transaction+not+found+REFID:4054582
+ authcode=
+ transactionid=
+ avsresponse=
+ cvvresponse=
+ orderid=1
+ type=void
+ response_code=300
+ ).join('&')
+ end
+end
diff --git a/test/unit/gateways/pin_test.rb b/test/unit/gateways/pin_test.rb
index c8edf25f776..975edc2db8e 100644
--- a/test/unit/gateways/pin_test.rb
+++ b/test/unit/gateways/pin_test.rb
@@ -202,7 +202,7 @@ def test_add_creditcard
assert_equal @credit_card.month, post[:card][:expiry_month]
assert_equal @credit_card.year, post[:card][:expiry_year]
assert_equal @credit_card.verification_value, post[:card][:cvc]
- assert_equal "#{@credit_card.first_name} #{@credit_card.last_name}", post[:card][:name]
+ assert_equal @credit_card.name, post[:card][:name]
end
def test_add_creditcard_with_card_token
diff --git a/test/unit/gateways/secure_pay_au_test.rb b/test/unit/gateways/secure_pay_au_test.rb
index 54b49c753ba..8684697067d 100644
--- a/test/unit/gateways/secure_pay_au_test.rb
+++ b/test/unit/gateways/secure_pay_au_test.rb
@@ -1,6 +1,8 @@
require 'test_helper'
class SecurePayAuTest < Test::Unit::TestCase
+ include CommStub
+
def setup
@gateway = SecurePayAuGateway.new(
:login => 'login',
@@ -48,6 +50,20 @@ def test_successful_purchase
assert response.test?
end
+ def test_localized_currency
+ stub_comms do
+ @gateway.purchase(100, @credit_card, @options.merge(:currency => 'CAD'))
+ end.check_request do |endpoint, data, headers|
+ assert_match /100<\/amount>/, data
+ end.respond_with(successful_purchase_response)
+
+ stub_comms do
+ @gateway.purchase(100, @credit_card, @options.merge(:currency => 'JPY'))
+ end.check_request do |endpoint, data, headers|
+ assert_match /1<\/amount>/, data
+ end.respond_with(successful_purchase_response)
+ end
+
def test_failed_purchase
@gateway.expects(:ssl_post).returns(failed_purchase_response)
diff --git a/test/unit/gateways/so_easy_pay_test.rb b/test/unit/gateways/so_easy_pay_test.rb
new file mode 100644
index 00000000000..daa8a9f9d35
--- /dev/null
+++ b/test/unit/gateways/so_easy_pay_test.rb
@@ -0,0 +1,225 @@
+require 'test_helper'
+
+class SoEasyPayTest < Test::Unit::TestCase
+ def setup
+ @gateway = SoEasyPayGateway.new(
+ :login => 'login',
+ :password => 'password'
+ )
+
+ @credit_card = credit_card
+ @amount = 100
+
+ @options = {
+ :order_id => '1',
+ :billing_address => address,
+ :description => 'Store Purchase'
+ }
+ end
+
+ def test_successful_purchase
+ @gateway.expects(:ssl_post).returns(successful_purchase_response)
+
+ assert response = @gateway.purchase(@amount, @credit_card, @options)
+ assert_instance_of Response, response
+ assert_success response
+
+ # Replace with authorization number from the successful response
+ assert_equal '1708978', response.authorization
+ assert response.test?
+ end
+
+ def test_unsuccessful_request
+ @gateway.expects(:ssl_post).returns(failed_purchase_response)
+
+ assert response = @gateway.purchase(@amount, @credit_card, @options)
+ assert_failure response
+ assert_equal '1708979', response.authorization
+ assert response.test?
+ end
+
+ def test_successful_authorize
+ @gateway.expects(:ssl_post).returns(successful_authorize_response)
+
+ assert response = @gateway.authorize(@amount, @credit_card, @options)
+ assert_instance_of Response, response
+ assert_success response
+
+ assert_equal('1708980', response.authorization)
+ assert response.test?
+ end
+
+ def test_successful_capture
+ @gateway.expects(:ssl_post).returns(successful_capture_response)
+
+ assert response = @gateway.capture(1111, "1708980")
+ assert_instance_of Response, response
+ assert_success response
+
+ assert_equal('1708981', response.authorization)
+ assert response.test?
+ end
+
+ def test_successful_refund
+ @gateway.expects(:ssl_post).returns(successful_credit_response)
+ assert response = @gateway.refund(@amount, '1708978')
+ assert_instance_of Response, response
+ assert_success response
+ assert_equal 'Transaction successful', response.message
+ end
+
+ def test_failed_refund
+ @gateway.expects(:ssl_post).returns(failed_credit_response)
+
+ assert response = @gateway.refund(@amount, '1708978')
+ assert_instance_of Response, response
+ assert_failure response
+ assert_equal 'Card declined', response.message
+ end
+
+ def test_do_not_depend_on_expiry_date_class
+ @gateway.stubs(:ssl_post).returns(successful_purchase_response)
+ @credit_card.expects(:expiry_date).never
+
+ @gateway.purchase(@amount, @credit_card, @options)
+ end
+
+ def test_use_ducktyping_for_credit_card
+ @gateway.expects(:ssl_post).returns(successful_purchase_response)
+
+ credit_card = stub(:number => '4242424242424242', :verification_value => '123', :name => "Hans Tester", :year => 2012, :month => 1)
+
+ assert_nothing_raised do
+ assert_success @gateway.purchase(@amount, credit_card, @options)
+ end
+ end
+
+ private
+
+ # Place raw successful response from gateway here
+ def successful_purchase_response
+ %(
+
+
+
+
+
+
+ 1708978
+ 12
+ Authorized
+ 000
+ Transaction successful
+ K
+ NOSCORE
+ 0000
+ **21
+ 02/16
+ VISA
+
+
+ )
+ end
+
+ # Place raw failed response from gateway here
+ def failed_purchase_response
+ %(
+
+
+
+
+
+
+ 1708979
+ 12
+ Not Authorized
+ 002
+ Card declined
+ K
+ NOSCORE
+ 0000
+ **21
+ 02/16
+ VISA
+
+
+ )
+ end
+
+ def successful_authorize_response
+ %(
+
+
+
+
+
+
+ 1708980
+ 12
+ Authorized
+ 000
+ Transaction successful
+ K
+ NOSCORE
+ 0000
+ **21
+ 02/16
+ VISA
+
+
+ )
+ end
+
+ def successful_capture_response
+ %(
+
+
+
+
+
+
+ 1708981
+ Authorized
+ 000
+ Transaction successful
+
+
+ )
+ end
+
+ def successful_credit_response
+ %(
+
+
+
+
+
+
+ 1708982
+ Authorized
+ 000
+ Transaction successful
+
+
+ )
+ end
+
+ def failed_credit_response
+ %(
+
+
+
+
+
+
+ 1708983
+ Not Authorized
+ 002
+ Card declined
+
+
+ )
+ end
+
+end
+
diff --git a/test/unit/gateways/spreedly_core_test.rb b/test/unit/gateways/spreedly_core_test.rb
index c2c3572e290..3f3bbb091b1 100644
--- a/test/unit/gateways/spreedly_core_test.rb
+++ b/test/unit/gateways/spreedly_core_test.rb
@@ -75,6 +75,16 @@ def test_failed_purchase_with_credit_card
assert_equal '0957', response.params['payment_method_last_four_digits']
end
+ def test_purchase_without_gateway_token_option
+ @gateway.expects(:commit).with("gateways/token/purchase.xml", anything)
+ @gateway.purchase(@amount, @payment_method_token)
+ end
+
+ def test_purchase_with_gateway_token_option
+ @gateway.expects(:commit).with("gateways/mynewtoken/purchase.xml", anything)
+ @gateway.purchase(@amount, @payment_method_token, gateway_token: 'mynewtoken')
+ end
+
def test_successful_authorize_with_token_and_capture
@gateway.expects(:raw_ssl_request).returns(successful_authorize_response)
response = @gateway.authorize(@amount, @payment_method_token)
diff --git a/test/unit/gateways/stripe_test.rb b/test/unit/gateways/stripe_test.rb
index 03898d4b2f5..9ef3407819c 100644
--- a/test/unit/gateways/stripe_test.rb
+++ b/test/unit/gateways/stripe_test.rb
@@ -16,6 +16,42 @@ def setup
}
end
+ def test_successful_new_customer_with_card
+ @gateway.expects(:ssl_request).returns(successful_new_customer_response)
+
+ assert response = @gateway.store(@credit_card, @options)
+ assert_instance_of Response, response
+ assert_success response
+
+ assert_equal 'cus_3sgheFxeBgTQ3M', response.authorization
+ assert response.test?
+ end
+
+ def test_successful_new_card
+ @gateway.expects(:ssl_request).returns(successful_new_card_response)
+
+ assert response = @gateway.store(@credit_card, @options.merge(:customer => 'cus_3sgheFxeBgTQ3M'))
+ assert_instance_of MultiResponse, response
+ assert_success response
+
+ assert_equal 'card_483etw4er9fg4vF3sQdrt3FG', response.authorization
+ assert response.test?
+ end
+
+ def test_successful_new_default_card
+ @gateway.expects(:ssl_request).twice.returns(successful_new_card_response, successful_new_customer_response)
+
+ assert response = @gateway.store(@credit_card, @options.merge(:customer => 'cus_3sgheFxeBgTQ3M', :set_default => true))
+ assert_instance_of MultiResponse, response
+ assert_success response
+
+ assert_equal 'card_483etw4er9fg4vF3sQdrt3FG', response.authorization
+ assert_equal 2, response.responses.size
+ assert_equal 'card_483etw4er9fg4vF3sQdrt3FG', response.responses[0].authorization
+ assert_equal 'cus_3sgheFxeBgTQ3M', response.responses[1].authorization
+ assert response.test?
+ end
+
def test_successful_authorization
@gateway.expects(:ssl_request).returns(successful_authorization_response)
@@ -47,6 +83,18 @@ def test_successful_purchase
assert response.test?
end
+ def test_successful_purchase_with_token
+ response = stub_comms(@gateway, :ssl_request) do
+ @gateway.purchase(@amount, "tok_xxx")
+ end.check_request do |method, endpoint, data, headers|
+ assert_match(/card=tok_xxx/, data)
+ end.respond_with(successful_purchase_response)
+
+ assert response
+ assert_instance_of Response, response
+ assert_success response
+ end
+
def test_successful_void
@gateway.expects(:ssl_request).returns(successful_purchase_response(true))
@@ -182,7 +230,7 @@ def test_add_creditcard_with_token_and_track_data
def test_add_customer
post = {}
- @gateway.send(:add_customer, post, {:customer => "test_customer"})
+ @gateway.send(:add_customer, post, @creditcard, {:customer => "test_customer"})
assert_equal "test_customer", post[:customer]
end
@@ -204,7 +252,7 @@ def test_application_fee_is_submitted_for_capture
def test_client_data_submitted_with_purchase
stub_comms(@gateway, :ssl_request) do
- updated_options = @options.merge({:description => "a test customer",:browser_ip => "127.127.127.127", :user_agent => "some browser", :order_id => "42", :email => "foo@wonderfullyfakedomain.com", :referrer =>"http://www.shopify.com"})
+ updated_options = @options.merge({:description => "a test customer",:ip => "127.127.127.127", :user_agent => "some browser", :order_id => "42", :email => "foo@wonderfullyfakedomain.com", :referrer =>"http://www.shopify.com"})
@gateway.purchase(@amount,@credit_card,updated_options)
end.check_request do |method, endpoint, data, headers|
assert_match(/description=a\+test\+customer/, data)
@@ -213,6 +261,7 @@ def test_client_data_submitted_with_purchase
assert_match(/external_id=42/, data)
assert_match(/referrer=http\%3A\%2F\%2Fwww\.shopify\.com/, data)
assert_match(/payment_user_agent=Stripe\%2Fv1\+ActiveMerchantBindings\%2F\d+\.\d+\.\d+/, data)
+ assert_match(/metadata\[email\]=foo\%40wonderfullyfakedomain\.com/, data)
end.respond_with(successful_purchase_response)
end
@@ -245,6 +294,14 @@ def test_metadata_header
@gateway.purchase(@amount, @credit_card, @options.merge(:ip => '1.1.1.1'))
end
+ def test_optional_version_header
+ @gateway.expects(:ssl_request).once.with {|method, url, post, headers|
+ headers && headers['Stripe-Version'] == '2013-10-29'
+ }.returns(successful_purchase_response)
+
+ @gateway.purchase(@amount, @credit_card, @options.merge(:version => '2013-10-29'))
+ end
+
def test_track_data_and_traditional_should_be_mutually_exclusive
stub_comms(@gateway, :ssl_request) do
@gateway.purchase(@amount, @credit_card, @options)
@@ -270,8 +327,89 @@ def test_address_is_included_with_card_data
end.respond_with(successful_purchase_response)
end
+ def generate_options_should_allow_key
+ assert_equal({:key => '12345'}, generate_options({:key => '12345'}))
+ end
+
private
+ # Create new customer and set default credit card
+ def successful_new_customer_response
+ <<-RESPONSE
+{
+ "object": "customer",
+ "created": 1383137317,
+ "id": "cus_3sgheFxeBgTQ3M",
+ "livemode": false,
+ "description": null,
+ "email": null,
+ "delinquent": false,
+ "metadata": {},
+ "subscription": null,
+ "discount": null,
+ "account_balance": 0,
+ "cards":
+ {
+ "object": "list",
+ "count": 1,
+ "url": "/v1/customers/cus_3sgheFxeBgTQ3M/cards",
+ "data":
+ [
+ {
+ "id": "card_483etw4er9fg4vF3sQdrt3FG",
+ "object": "card",
+ "last4": "4242",
+ "type": "Visa",
+ "exp_month": 11,
+ "exp_year": 2020,
+ "fingerprint": "5dgRQ3dVRGaQWDFb",
+ "customer": "cus_3sgheFxeBgTQ3M",
+ "country": "US",
+ "name": "John Doe",
+ "address_line1": null,
+ "address_line2": null,
+ "address_city": null,
+ "address_state": null,
+ "address_zip": null,
+ "address_country": null,
+ "cvc_check": null,
+ "address_line1_check": null,
+ "address_zip_check": null
+ }
+ ]
+ },
+ "default_card": "card_483etw4er9fg4vF3sQdrt3FG"
+}
+ RESPONSE
+ end
+
+ def successful_new_card_response
+ <<-RESPONSE
+{
+ "id": "card_483etw4er9fg4vF3sQdrt3FG",
+ "livemode": false,
+ "object": "card",
+ "last4": "4242",
+ "type": "Visa",
+ "exp_month": 11,
+ "exp_year": 2020,
+ "fingerprint": "5dgRQ3dVRGaQWDFb",
+ "customer": "cus_3sgheFxeBgTQ3M",
+ "country": "US",
+ "name": "John Doe",
+ "address_line1": null,
+ "address_line2": null,
+ "address_city": null,
+ "address_state": null,
+ "address_zip": null,
+ "address_country": null,
+ "cvc_check": null,
+ "address_line1_check": null,
+ "address_zip_check": null
+}
+ RESPONSE
+ end
+
def successful_authorization_response
<<-RESPONSE
{
diff --git a/test/unit/gateways/swipe_checkout_test.rb b/test/unit/gateways/swipe_checkout_test.rb
new file mode 100644
index 00000000000..e6c4e0da63a
--- /dev/null
+++ b/test/unit/gateways/swipe_checkout_test.rb
@@ -0,0 +1,154 @@
+require 'test_helper'
+
+class SwipeCheckoutTest < Test::Unit::TestCase
+ def setup
+ @gateway = SwipeCheckoutGateway.new(
+ login: '0000000000000',
+ api_key: '0000000000000000000000000000000000000000000000000000000000000000',
+ region: 'NZ'
+ )
+
+ @credit_card = credit_card
+ @amount = 100
+
+ @options = {
+ order_id: '1',
+ billing_address: address,
+ description: 'Store Purchase'
+ }
+ end
+
+ def test_supported_countries
+ assert @gateway.supported_countries == ['NZ', 'CA']
+ end
+
+ def test_successful_purchase
+ @gateway.expects(:ssl_post).returns(successful_purchase_response)
+
+ assert response = @gateway.purchase(@amount, @credit_card, @options)
+ assert_instance_of Response, response
+ assert_success response
+ assert_equal 'Transaction approved', response.message
+ assert response.test?
+ end
+
+ def test_successful_test_purchase
+ @gateway.expects(:ssl_post).returns(successful_test_purchase_response)
+
+ assert response = @gateway.purchase(@amount, @credit_card, @options)
+ assert_instance_of Response, response
+
+ assert_success response
+ assert response.test?
+ end
+
+ def test_unsuccessful_purchase
+ @gateway.expects(:ssl_post).returns(failed_purchase_response)
+
+ assert response = @gateway.purchase(@amount, @credit_card, @options)
+ assert_failure response
+ assert response.test?
+ end
+
+ def test_unsuccessful_test_purchase
+ @gateway.expects(:ssl_post).returns(failed_test_purchase_response)
+
+ assert response = @gateway.purchase(@amount, @credit_card, @options)
+ assert_failure response
+ assert response.test?
+ end
+
+ def test_unsuccessful_request_invalid_card
+ @gateway.expects(:ssl_post).returns(failed_purchase_response_invalid_card)
+
+ assert response = @gateway.purchase(@amount, @credit_card, @options)
+ assert_failure response
+ assert response.test?
+ end
+
+ def test_unsuccessful_request_system_error
+ @gateway.expects(:ssl_post).returns(failed_purchase_response_system_error)
+
+ assert response = @gateway.purchase(@amount, @credit_card, @options)
+ assert_failure response
+ assert response.test?
+ end
+
+ def test_unsuccessful_request_incorrect_amount
+ @gateway.expects(:ssl_post).returns(failed_purchase_response_incorrect_amount)
+
+ assert response = @gateway.purchase(@amount, @credit_card, @options)
+ assert_failure response
+ assert response.test?
+ end
+
+ def test_unsuccessful_request_access_denied
+ @gateway.expects(:ssl_post).returns(failed_purchase_response_access_denied)
+
+ assert response = @gateway.purchase(@amount, @credit_card, @options)
+ assert_failure response
+ assert response.test?
+ end
+
+ def test_unsuccessful_request_not_enough_parameters
+ @gateway.expects(:ssl_post).returns(failed_purchase_response_not_enough_parameters)
+
+ assert response = @gateway.purchase(@amount, @credit_card, @options)
+ assert_failure response
+ assert response.test?
+ end
+
+ def test_unsuccessful_request_invalid_json_in_response
+ @gateway.expects(:ssl_post).returns(response_with_invalid_json)
+
+ assert response = @gateway.purchase(@amount, @credit_card, @options)
+ assert_failure response
+ assert response.test?
+ end
+
+ private
+
+ def successful_purchase_response
+ '{"response_code": 200, "message": "OK", "data": {"tx_transaction_id": "00000000000000", "result": "accepted"}}'
+ end
+
+ def successful_test_purchase_response
+ '{"response_code": 200, "message": "OK", "data": {"tx_transaction_id": "00000000000000", "result": "test-accepted"}}'
+ end
+
+ def failed_purchase_response
+ '{"response_code": 200, "message": "OK", "data": {"tx_transaction_id": "00000000000000", "result": "declined"}}'
+ end
+
+ def failed_test_purchase_response
+ '{"response_code": 200, "message": "OK", "data": {"tx_transaction_id": "00000000000000", "result": "test-declined"}}'
+ end
+
+ def failed_purchase_response_invalid_card
+ build_failed_response 303, 'Invalid card data'
+ end
+
+ def failed_purchase_response_system_error
+ build_failed_response 402, 'System error'
+ end
+
+ def failed_purchase_response_incorrect_amount
+ build_failed_response 302, 'Incorrect amount'
+ end
+
+ def failed_purchase_response_access_denied
+ build_failed_response 400, 'System error'
+ end
+
+ def failed_purchase_response_not_enough_parameters
+ build_failed_response 403, 'Not enough parameters'
+ end
+
+ def response_with_invalid_json
+ '{"response_code": '
+ end
+
+ def build_failed_response(code, message)
+ "{\"response_code\": #{code}, \"message\": \"#{message}\"}"
+ end
+end
diff --git a/test/unit/gateways/usa_epay_transaction_test.rb b/test/unit/gateways/usa_epay_transaction_test.rb
index 681682e8ea2..933c76c6602 100644
--- a/test/unit/gateways/usa_epay_transaction_test.rb
+++ b/test/unit/gateways/usa_epay_transaction_test.rb
@@ -4,17 +4,35 @@ class UsaEpayTransactionTest < Test::Unit::TestCase
include CommStub
def setup
- @gateway = UsaEpayTransactionGateway.new(
- :login => 'LOGIN'
- )
+ @gateway = UsaEpayTransactionGateway.new(:login => 'LOGIN')
@credit_card = credit_card('4242424242424242')
@options = {
- :billing_address => address,
+ :billing_address => address,
:shipping_address => address
}
@amount = 100
end
+
+ def test_urls
+ assert_equal 'https://www.usaepay.com/gate', UsaEpayTransactionGateway.live_url
+ assert_equal 'https://sandbox.usaepay.com/gate', UsaEpayTransactionGateway.test_url
+ end
+
+ def test_request_url_live
+ gateway = UsaEpayTransactionGateway.new(:login => 'LOGIN', :test => false)
+ gateway.expects(:ssl_post).
+ with('https://www.usaepay.com/gate', purchase_request).
+ returns(successful_purchase_response)
+ assert response = gateway.purchase(@amount, @credit_card, @options)
+ end
+
+ def test_request_url_test
+ @gateway.expects(:ssl_post).
+ with('https://sandbox.usaepay.com/gate', purchase_request).
+ returns(successful_purchase_response)
+ assert response = @gateway.purchase(@amount, @credit_card, @options)
+ end
def test_successful_request
@gateway.expects(:ssl_post).returns(successful_purchase_response)
@@ -42,6 +60,42 @@ def test_successful_purchase_passing_extra_info
end.respond_with(successful_purchase_response)
assert_success response
end
+
+ def test_successful_purchase_split_payment
+ response = stub_comms do
+ @gateway.purchase(@amount, @credit_card, @options.merge(
+ :split_payments => [
+ { :key => 'abc123', :amount => 199, :description => 'Second payee' },
+ { :key => 'def456', :amount => 911, :description => 'Third payee' },
+ ]
+ ))
+ end.check_request do |endpoint, data, headers|
+ assert_match /UM02key=abc123/, data
+ assert_match /UM02amount=1.99/, data
+ assert_match /UM02description=Second\+payee/, data
+
+ assert_match /UM03key=def456/, data
+ assert_match /UM03amount=9.11/, data
+ assert_match /UM03description=Third\+payee/, data
+
+ assert_match /UMonError=Void/, data
+ end.respond_with(successful_purchase_response)
+ assert_success response
+ end
+
+ def test_successful_purchase_split_payment_with_custom_on_error
+ response = stub_comms do
+ @gateway.purchase(@amount, @credit_card, @options.merge(
+ :split_payments => [
+ { :key => 'abc123', :amount => 199, :description => 'Second payee' }
+ ],
+ :on_error => 'Continue'
+ ))
+ end.check_request do |endpoint, data, headers|
+ assert_match /UMonError=Continue/, data
+ end.respond_with(successful_purchase_response)
+ assert_success response
+ end
def test_address_key_prefix
assert_equal 'bill', @gateway.send(:address_key_prefix, :billing)
@@ -115,20 +169,20 @@ def test_does_not_raise_error_on_missing_values
end
end
- private
+private
def assert_address(type, post)
prefix = key_prefix(type)
- assert_equal @credit_card.first_name, post[key(prefix, 'fname')]
- assert_equal @credit_card.last_name, post[key(prefix, 'lname')]
- assert_equal @options[:billing_address][:company], post[key(prefix, 'company')]
+ assert_equal @credit_card.first_name, post[key(prefix, 'fname')]
+ assert_equal @credit_card.last_name, post[key(prefix, 'lname')]
+ assert_equal @options[:billing_address][:company], post[key(prefix, 'company')]
assert_equal @options[:billing_address][:address1], post[key(prefix, 'street')]
assert_equal @options[:billing_address][:address2], post[key(prefix, 'street2')]
- assert_equal @options[:billing_address][:city], post[key(prefix, 'city')]
- assert_equal @options[:billing_address][:state], post[key(prefix, 'state')]
- assert_equal @options[:billing_address][:zip], post[key(prefix, 'zip')]
- assert_equal @options[:billing_address][:country], post[key(prefix, 'country')]
- assert_equal @options[:billing_address][:phone], post[key(prefix, 'phone')]
+ assert_equal @options[:billing_address][:city], post[key(prefix, 'city')]
+ assert_equal @options[:billing_address][:state], post[key(prefix, 'state')]
+ assert_equal @options[:billing_address][:zip], post[key(prefix, 'zip')]
+ assert_equal @options[:billing_address][:country], post[key(prefix, 'country')]
+ assert_equal @options[:billing_address][:phone], post[key(prefix, 'phone')]
end
def key_prefix(type)
@@ -138,6 +192,10 @@ def key_prefix(type)
def key(prefix, key)
@gateway.send(:address_key, prefix, key)
end
+
+ def purchase_request
+ "UMamount=1.00&UMinvoice=&UMdescription=&UMcard=4242424242424242&UMcvv2=123&UMexpir=0914&UMname=Longbob+Longsen&UMbillfname=Longbob&UMbilllname=Longsen&UMbillcompany=Widgets+Inc&UMbillstreet=1234+My+Street&UMbillstreet2=Apt+1&UMbillcity=Ottawa&UMbillstate=ON&UMbillzip=K1C2N6&UMbillcountry=CA&UMbillphone=%28555%29555-5555&UMshipfname=Longbob&UMshiplname=Longsen&UMshipcompany=Widgets+Inc&UMshipstreet=1234+My+Street&UMshipstreet2=Apt+1&UMshipcity=Ottawa&UMshipstate=ON&UMshipzip=K1C2N6&UMshipcountry=CA&UMshipphone=%28555%29555-5555&UMstreet=1234+My+Street&UMzip=K1C2N6&UMcommand=cc%3Asale&UMkey=LOGIN&UMsoftware=Active+Merchant&UMtestmode=0"
+ end
def successful_purchase_response
"UMversion=2.9&UMstatus=Approved&UMauthCode=001716&UMrefNum=55074409&UMavsResult=Address%3A%20Match%20%26%205%20Digit%20Zip%3A%20Match&UMavsResultCode=Y&UMcvv2Result=Match&UMcvv2ResultCode=M&UMresult=A&UMvpasResultCode=&UMerror=Approved&UMerrorcode=00000&UMcustnum=&UMbatch=596&UMisDuplicate=N&UMconvertedAmount=&UMconvertedAmountCurrency=840&UMconversionRate=&UMcustReceiptResult=No%20Receipt%20Sent&UMfiller=filled"
diff --git a/test/unit/gateways/webpay_test.rb b/test/unit/gateways/webpay_test.rb
index 1e6d9406c9c..87a08584fe7 100644
--- a/test/unit/gateways/webpay_test.rb
+++ b/test/unit/gateways/webpay_test.rb
@@ -1,6 +1,8 @@
require 'test_helper'
class WebpayTest < Test::Unit::TestCase
+ include CommStub
+
def setup
@gateway = WebpayGateway.new(:login => 'login')
@@ -14,6 +16,25 @@ def setup
}
end
+ def test_successful_authorization
+ @gateway.expects(:ssl_request).returns(successful_authorization_response)
+
+ assert response = @gateway.authorize(@amount, @credit_card, @options)
+ assert_instance_of Response, response
+ assert_success response
+
+ assert_equal 'ch_test_charge', response.authorization
+ assert response.test?
+ end
+
+ def test_successful_capture
+ @gateway.expects(:ssl_request).returns(successful_capture_response)
+
+ assert response = @gateway.capture(@amount, "ch_test_charge")
+ assert_success response
+ assert response.test?
+ end
+
def test_successful_purchase
@gateway.expects(:ssl_request).returns(successful_purchase_response)
@@ -26,7 +47,7 @@ def test_successful_purchase
assert response.test?
end
- def test_appropiate_purchase_amount
+ def test_appropriate_purchase_amount
@gateway.expects(:ssl_request).returns(successful_purchase_response)
response = @gateway.purchase(@amount, @credit_card, @options)
@@ -36,6 +57,17 @@ def test_appropiate_purchase_amount
assert_equal @amount / 100, response.params["amount"]
end
+ def test_successful_purchase_with_token
+ response = stub_comms(@gateway, :ssl_request) do
+ @gateway.purchase(@amount, "tok_xxx")
+ end.check_request do |method, endpoint, data, headers|
+ assert_match(/card=tok_xxx/, data)
+ end.respond_with(successful_purchase_response)
+
+ assert response
+ assert_instance_of Response, response
+ assert_success response
+ end
def test_successful_void
@gateway.expects(:ssl_request).returns(successful_purchase_response(true))
@@ -88,13 +120,13 @@ def test_invalid_raw_response
def test_add_customer
post = {}
- @gateway.send(:add_customer, post, {:customer => "test_customer"})
+ @gateway.send(:add_customer, post, 'card_token', {:customer => "test_customer"})
assert_equal "test_customer", post[:customer]
end
def test_doesnt_add_customer_if_card
- post = { :card => 'foo' }
- @gateway.send(:add_customer, post, {:customer => "test_customer"})
+ post = {}
+ @gateway.send(:add_customer, post, @credit_card, {:customer => "test_customer"})
assert !post[:customer]
end
@@ -134,6 +166,66 @@ def test_metadata_header
private
+ def successful_authorization_response
+ <<-RESPONSE
+{
+ "id": "ch_test_charge",
+ "object": "charge",
+ "created": 1309131571,
+ "livemode": false,
+ "paid": true,
+ "amount": 40000,
+ "currency": "jpy",
+ "refunded": false,
+ "fee": 0,
+ "fee_details": [],
+ "card": {
+ "country": "JP",
+ "exp_month": 9,
+ "exp_year": #{Time.now.year + 1},
+ "last4": "4242",
+ "object": "card",
+ "type": "Visa"
+ },
+ "captured": false,
+ "description": "ActiveMerchant Test Purchase",
+ "dispute": null,
+ "uncaptured": true,
+ "disputed": false
+}
+ RESPONSE
+ end
+
+ def successful_capture_response
+ <<-RESPONSE
+{
+ "id": "ch_test_charge",
+ "object": "charge",
+ "created": 1309131571,
+ "livemode": false,
+ "paid": true,
+ "amount": 40000,
+ "currency": "jpy",
+ "refunded": false,
+ "fee": 0,
+ "fee_details": [],
+ "card": {
+ "country": "JP",
+ "exp_month": 9,
+ "exp_year": #{Time.now.year + 1},
+ "last4": "4242",
+ "object": "card",
+ "type": "Visa"
+ },
+ "captured": true,
+ "description": "ActiveMerchant Test Purchase",
+ "dispute": null,
+ "uncaptured": false,
+ "disputed": false
+}
+ RESPONSE
+ end
+
# Place raw successful response from gateway here
def successful_purchase_response(refunded=false)
<<-RESPONSE
diff --git a/test/unit/gateways/wirecard_test.rb b/test/unit/gateways/wirecard_test.rb
index 6a1a75218ac..61c2883a9e3 100644
--- a/test/unit/gateways/wirecard_test.rb
+++ b/test/unit/gateways/wirecard_test.rb
@@ -77,6 +77,32 @@ def test_successful_authorization_and_capture
assert response.message[/this is a demo/i]
end
+ def test_successful_refund
+ @gateway.expects(:ssl_post).returns(successful_purchase_response)
+ assert response = @gateway.purchase(@amount, @credit_card, @options)
+ assert_success response
+ assert_equal TEST_PURCHASE_GUWID, response.authorization
+
+ @gateway.expects(:ssl_post).returns(successful_refund_response)
+ assert response = @gateway.refund(@amount - 30, response.authorization, @options)
+ assert_success response
+ assert response.test?
+ assert_match /All good!/, response.message
+ end
+
+ def test_successful_void
+ @gateway.expects(:ssl_post).returns(successful_purchase_response)
+ assert response = @gateway.purchase(@amount, @credit_card, @options)
+ assert_success response
+ assert_equal TEST_PURCHASE_GUWID, response.authorization
+
+ @gateway.expects(:ssl_post).returns(successful_void_response)
+ assert response = @gateway.void(response.authorization, @options)
+ assert_success response
+ assert response.test?
+ assert_match /Nice one!/, response.message
+ end
+
def test_successful_authorization_and_partial_capture
@gateway.expects(:ssl_post).returns(successful_authorization_response)
assert response = @gateway.authorize(@amount, @credit_card, @options)
@@ -99,6 +125,20 @@ def test_unauthorized_capture
assert response.message["Could not find referenced transaction for GuWID 1234567890123456789012."]
end
+ def test_failed_refund
+ @gateway.expects(:ssl_post).returns(failed_refund_response)
+ assert response = @gateway.refund(@amount - 30, "TheIdentifcation", @options)
+ assert_failure response
+ assert_match /Not prudent/, response.message
+ end
+
+ def test_failed_void
+ @gateway.expects(:ssl_post).returns(failed_void_response)
+ assert response = @gateway.refund(@amount - 30, "TheIdentifcation", @options)
+ assert_failure response
+ assert_match /Not gonna do it/, response.message
+ end
+
def test_no_error_if_no_state_is_provided_in_address
options = @options.merge(:billing_address => @address_without_state)
@gateway.expects(:ssl_post).returns(unauthorized_capture_response)
@@ -272,6 +312,123 @@ def successful_purchase_response
XML
end
+ def successful_refund_response
+ <<-XML
+
+
+
+
+
+
+
+
+ 2a486b3ab747df694d5460c3cb444591
+
+ C898842138247065382261
+ 424492
+ All good!
+ INFO
+ ACK
+ 2013-10-22 21:37:33
+
+
+
+
+
+
+ XML
+ end
+
+ def failed_refund_response
+ <<-XML
+
+
+
+
+
+
+
+
+ 98680cbeee81d32e94a2b71397ffdf88
+
+ C999187138247102291030
+
+ INFO
+ NOK
+
+ DATA_ERROR
+ 20080
+ Not prudent
+
+ 2013-10-22 21:43:42
+
+
+
+
+
+
+ XML
+ end
+
+ def successful_void_response
+ <<-XML
+
+
+
+
+
+
+
+
+ 5f1a2ab3fb2ed7a6aaa0eea74dc109e2
+
+ C907807138247383379288
+ 802187
+ Nice one!
+ INFO
+ ACK
+ 2013-10-22 22:30:33
+
+
+
+
+
+
+ XML
+ end
+
+ def failed_void_response
+ <<-XML
+
+
+
+
+
+
+
+
+ c11154e9395cf03c49bd68ec5c7087cc
+
+ C941776138247400010330
+
+ INFO
+ NOK
+
+ DATA_ERROR
+ 20080
+ Not gonna do it
+
+ 2013-10-22 22:33:20
+
+
+
+
+
+
+ XML
+ end
+
+
# Purchase failure
def wrong_creditcard_purchase_response
<<-XML
diff --git a/test/unit/integrations/bit_pay_module_test.rb b/test/unit/integrations/bit_pay_module_test.rb
index 0596d60e6c0..8cd7f204788 100644
--- a/test/unit/integrations/bit_pay_module_test.rb
+++ b/test/unit/integrations/bit_pay_module_test.rb
@@ -4,6 +4,10 @@ class BitPayModuleTest < Test::Unit::TestCase
include ActiveMerchant::Billing::Integrations
def test_notification_method
- assert_instance_of BitPay::Notification, BitPay.notification('name=cody')
+ assert_instance_of BitPay::Notification, BitPay.notification('{"name":"cody"}', {})
+ end
+
+ def test_return_method
+ assert_instance_of BitPay::Return, BitPay.return('{"name":"cody"}', {})
end
end
diff --git a/test/unit/integrations/helpers/bit_pay_helper_test.rb b/test/unit/integrations/helpers/bit_pay_helper_test.rb
index 5f8ee5f5986..8942ca2d56a 100644
--- a/test/unit/integrations/helpers/bit_pay_helper_test.rb
+++ b/test/unit/integrations/helpers/bit_pay_helper_test.rb
@@ -4,14 +4,12 @@ class BitPayHelperTest < Test::Unit::TestCase
include ActiveMerchant::Billing::Integrations
def setup
- BitPay::Helper.any_instance.expects(:generate_invoice_id).once.returns(nil)
- @helper = BitPay::Helper.new(1234, 'cody@example.com', :authcode => "foobar", :amount => 500, :currency => 'USD')
+ @helper = BitPay::Helper.new(1234, 'cody@example.com', :amount => 500, :currency => 'USD')
end
def test_basic_helper_fields
assert_field 'orderID', "1234"
assert_field 'price', "500"
- assert_field 'posData', 'foobar'
assert_field 'currency', 'USD'
end
@@ -46,4 +44,10 @@ def test_setting_invalid_address_field
@helper.billing_address :street => 'My Street'
assert_equal fields, @helper.fields
end
+
+ def test_form_fields_uses_invoice_id
+ Net::HTTP.any_instance.expects(:request).returns(stub(:body => '{"id": "98kui1gJ7FocK41gUaBZxG"}'))
+
+ assert_equal '98kui1gJ7FocK41gUaBZxG', @helper.form_fields['id']
+ end
end
diff --git a/test/unit/integrations/helpers/ipay88_helper_test.rb b/test/unit/integrations/helpers/ipay88_helper_test.rb
index 675ba816728..84b475505a6 100644
--- a/test/unit/integrations/helpers/ipay88_helper_test.rb
+++ b/test/unit/integrations/helpers/ipay88_helper_test.rb
@@ -95,9 +95,19 @@ def test_invalid_amount_as_negative_integer_in_cents
end
def test_sig_components_amount_doesnt_include_decimal_points
- @helper.amount = 0.5
- assert_equal "abcipay88merchcodeorder-50005MYR", @helper.send(:sig_components)
- @helper.amount = 12.34
+ @helper.amount = 50
+ assert_equal "abcipay88merchcodeorder-500050MYR", @helper.send(:sig_components)
+ @helper.amount = 1234
assert_equal "abcipay88merchcodeorder-5001234MYR", @helper.send(:sig_components)
+ @helper.amount = 1000
+ assert_equal "abcipay88merchcodeorder-5001000MYR", @helper.send(:sig_components)
+ @helper.amount = Money.new(90)
+ assert_equal "abcipay88merchcodeorder-500090MYR", @helper.send(:sig_components)
+ @helper.amount = Money.new(1000)
+ assert_equal "abcipay88merchcodeorder-5001000MYR", @helper.send(:sig_components)
+ end
+
+ def test_sign_method
+ assert_equal "rq3VxZp9cjkiqiw4mHnZJH49MzQ=", Ipay88::Helper.sign("L3mn6Bpy4HM0605613619416109MYR")
end
end
diff --git a/test/unit/integrations/helpers/payu_in_helper_test.rb b/test/unit/integrations/helpers/payu_in_helper_test.rb
index 20d7f368319..2d210a59440 100644
--- a/test/unit/integrations/helpers/payu_in_helper_test.rb
+++ b/test/unit/integrations/helpers/payu_in_helper_test.rb
@@ -4,14 +4,13 @@ class PayuInHelperTest < Test::Unit::TestCase
include ActiveMerchant::Billing::Integrations
def setup
- @helper = PayuIn::Helper.new( 'jh34h53kj4h5hj34kh5', 'C0Dr8m', :amount => '10.00', :credential2 => 'Product Info')
+ @helper = PayuIn::Helper.new( 'order_id', 'merchant_id', :amount => '10.00', :credential2 => 'secret_key')
end
def test_basic_helper_fields
assert_equal '10.00', @helper.fields['amount']
- assert_equal 'C0Dr8m', @helper.fields['key']
- assert_equal 'jh34h53kj4h5hj34kh5', @helper.fields['txnid']
- assert_equal 'Product Info', @helper.fields['productinfo']
+ assert_equal 'merchant_id', @helper.fields['key']
+ assert_equal 'order_id', @helper.fields['txnid']
end
def test_customer_fields
@@ -56,11 +55,20 @@ def test_user_defined_fields
end
def test_add_checksum_method
- options = { :mode => 'CC' }
@helper.customer :first_name => 'Payu-Admin', :email => 'test@example.com'
+ @helper.description "Product Info"
@helper.user_defined :var1 => 'var_one', :var2 => 'var_two', :var3 => 'var_three', :var4 => 'var_four', :var5 => 'var_five', :var6 => 'var_six', :var7 => 'var_seven', :var8 => 'var_eight', :var9 => 'var_nine', :var10 => 'var_ten'
- assert_equal "032606d7fb5cfe357d9e6b358b4bb8db1d34e9dfa30f039cb7dec75ae6d77f7d1f67a58c123ea0ee358bf040554d5e3048066a369ae63888132e27c14e79ee5a", @helper.form_fields["hash"]
+ fields = ["txnid", "amount", "productinfo", "firstname", "email", "udf1", "udf2", "udf3", "udf4", "udf5", "udf6", "udf7", "udf8", "udf9", "udf10"].map { |field| @helper.fields[field] }
+ assert_equal Digest::SHA512.hexdigest(['merchant_id', *fields, 'secret_key'].join("|")), @helper.form_fields["hash"]
+ end
+
+ def test_sanitize_fields_in_form_fields
+ @helper.description '{[Valid Description!]}'
+ @helper.form_fields
+
+ assert_equal 'Valid Description', @helper.fields['productinfo']
+ assert_nil @helper.fields['email']
end
end
diff --git a/test/unit/integrations/helpers/payu_in_paisa_helper_test.rb b/test/unit/integrations/helpers/payu_in_paisa_helper_test.rb
index b4e9a2c2e5f..31e6e4ae4fd 100644
--- a/test/unit/integrations/helpers/payu_in_paisa_helper_test.rb
+++ b/test/unit/integrations/helpers/payu_in_paisa_helper_test.rb
@@ -4,14 +4,13 @@ class PayuInPaisaHelperTest < Test::Unit::TestCase
include ActiveMerchant::Billing::Integrations
def setup
- @helper = PayuInPaisa::Helper.new( 'jh34h53kj4h5hj34kh5', 'C0Dr8m', :amount => '10.00', :credential2 => 'Product Info')
+ @helper = PayuInPaisa::Helper.new( 'order_id', 'merchant_id', :amount => '10.00', :credential2 => 'secret')
end
def test_basic_helper_fields
assert_equal '10.00', @helper.fields['amount']
- assert_equal 'C0Dr8m', @helper.fields['key']
- assert_equal 'jh34h53kj4h5hj34kh5', @helper.fields['txnid']
- assert_equal 'Product Info', @helper.fields['productinfo']
+ assert_equal 'merchant_id', @helper.fields['key']
+ assert_equal 'order_id', @helper.fields['txnid']
end
def test_customer_fields
@@ -56,10 +55,12 @@ def test_user_defined_fields
end
def test_add_checksum_method
- options = { :mode => 'CC' }
@helper.customer :first_name => 'Payu-Admin', :email => 'test@example.com'
@helper.user_defined :var1 => 'var_one', :var2 => 'var_two', :var3 => 'var_three', :var4 => 'var_four', :var5 => 'var_five', :var6 => 'var_six', :var7 => 'var_seven', :var8 => 'var_eight', :var9 => 'var_nine', :var10 => 'var_ten'
+ @helper.description 'Product Info'
- assert_equal "032606d7fb5cfe357d9e6b358b4bb8db1d34e9dfa30f039cb7dec75ae6d77f7d1f67a58c123ea0ee358bf040554d5e3048066a369ae63888132e27c14e79ee5a", @helper.form_fields["hash"]
+ payload = 'merchant_id|order_id|10.00|Product Info|Payu-Admin|test@example.com|var_one|var_two|var_three|var_four|var_five|var_six|var_seven|var_eight|var_nine|var_ten|secret'
+ checksum = Digest::SHA512.hexdigest(payload)
+ assert_equal checksum, @helper.form_fields["hash"]
end
end
diff --git a/test/unit/integrations/helpers/valitor_helper_test.rb b/test/unit/integrations/helpers/valitor_helper_test.rb
index 64519cb9470..13a4b1e73cc 100644
--- a/test/unit/integrations/helpers/valitor_helper_test.rb
+++ b/test/unit/integrations/helpers/valitor_helper_test.rb
@@ -20,7 +20,7 @@ def test_basic_helper_fields
assert_field 'Tilvisunarnumer', 'order-500'
assert_field 'Gjaldmidill', 'USD'
- assert_equal Digest::MD5.hexdigest(['123', '0', '1', '1000', '0', 'cody@example.com', 'order-500', 'USD'].join('')),
+ assert_equal Digest::MD5.hexdigest(['123', '0', '1', '1000.00', '0', 'cody@example.com', 'order-500', 'USD'].join('')),
@helper.form_fields['RafraenUndirskrift']
end
@@ -30,18 +30,18 @@ def test_products
assert_field 'Vara_1_Lysing', 'one'
assert_field 'Vara_1_Fjoldi', '2'
- assert_field 'Vara_1_Verd', '100'
+ assert_field 'Vara_1_Verd', '100.00'
assert_field 'Vara_1_Afslattur', '50'
assert_field 'Vara_2_Lysing', 'two'
assert_field 'Vara_2_Fjoldi', '1'
- assert_field 'Vara_2_Verd', '200'
+ assert_field 'Vara_2_Verd', '200.00'
assert_field 'Vara_2_Afslattur', '0'
assert_equal Digest::MD5.hexdigest(
['123', '0',
- '2', '100', '50',
- '1', '200', '0',
+ '2', '100.00', '50',
+ '1', '200.00', '0',
'cody@example.com', 'order-500', 'USD'].join('')),
@helper.form_fields['RafraenUndirskrift']
end
@@ -100,7 +100,7 @@ def test_urls
assert_equal Digest::MD5.hexdigest(
['123', '0',
- '1', '1000', '0',
+ '1', '1000.00', '0',
'cody@example.com', 'order-500', 'http://example.com/return', 'http://example.com/notify', 'USD'].join('')),
@helper.form_fields['RafraenUndirskrift']
end
@@ -127,9 +127,15 @@ def test_misc_mappings
assert_field 'Lang', 'en'
end
- def test_amount_gets_sent_without_decimals
+ def test_amount_gets_sent_without_decimals_for_non_decimal_currencies
@helper = Valitor::Helper.new('order-500', 'cody@example.com', :currency => 'ISK', :credential2 => '123', :amount => 115.10)
@helper.form_fields
assert_field "Vara_1_Verd", '115'
end
+
+ def test_amount_gets_sent_with_decimals_for_decimal_currencies
+ @helper = Valitor::Helper.new('order-500', 'cody@example.com', :currency => 'USD', :credential2 => '123', :amount => 115.10)
+ @helper.form_fields
+ assert_field "Vara_1_Verd", '115.10'
+ end
end
diff --git a/test/unit/integrations/helpers/wirecard_checkout_page_helper_test.rb b/test/unit/integrations/helpers/wirecard_checkout_page_helper_test.rb
new file mode 100644
index 00000000000..b90e56ef542
--- /dev/null
+++ b/test/unit/integrations/helpers/wirecard_checkout_page_helper_test.rb
@@ -0,0 +1,89 @@
+require 'test_helper'
+
+class WirecardCheckoutPageHelperTest < Test::Unit::TestCase
+ include ActiveMerchant::Billing::Integrations
+
+ def setup
+ @options = fixtures(:wirecard_checkout_page)
+ @helper = WirecardCheckoutPage::Helper.new('13', 'D200001', @options)
+
+ @helper.max_retries = 3
+ @helper.auto_deposit = true
+ @helper.add_version('Some Shopsystem', '0.0.1')
+
+ @helper.language 'de'
+ @helper.description 'Order Number 13'
+ @helper.shop_service_url 'http://www.example.com/imprint'
+ @helper.notify_url "https://www.example.com/payment/confirm"
+ @helper.return_url "http://www.example.com/payment/return"
+ @helper.cancel_return_url "http://www.example.com/payment/return"
+ @helper.pending_url "http://www.example.com/payment/return"
+ @helper.failure_url "http://www.example.com/payment/return"
+ end
+
+ def test_basic_helper_fields
+ assert_field 'language', 'de'
+ assert_field 'orderDescription', 'Order Number 13'
+ assert_field 'serviceUrl', 'http://www.example.com/imprint'
+ assert_field 'autoDeposit', "true"
+ assert_field 'confirmUrl', "https://www.example.com/payment/confirm"
+ assert_field 'successUrl', "http://www.example.com/payment/return"
+ assert_field 'cancelUrl', "http://www.example.com/payment/return"
+ assert_field 'pendingUrl', "http://www.example.com/payment/return"
+ assert_field 'failureUrl', "http://www.example.com/payment/return"
+ assert_field 'maxRetries', "3"
+ assert @helper.secret == 'B8AKTPWBRMNBV455FG6M2DANE99WU2'
+ assert @helper.customer_id == 'D200001'
+ assert @helper.shop_id == ''
+ end
+
+ def test_customer_fields
+ @helper.customer :first_name => 'Sepp',
+ :last_name => 'Maier',
+ :ipaddress => '127.0.0.1',
+ :user_agent => 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0',
+ :email => 'foo@bar.com'
+
+ assert_field 'consumerBillingFirstName', 'Sepp'
+ assert_field 'consumerBillingLastName', 'Maier'
+ assert_field 'consumerIpAddress', '127.0.0.1'
+ assert_field 'consumerUserAgent', 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0'
+ assert_field 'consumerEmail', 'foo@bar.com'
+ end
+
+ def test_address_mapping
+ @helper.billing_address(:address1 => 'Daham 99',
+ :zip => '8010',
+ :city => 'Graz',
+ :state => 'Steiermark',
+ :country => 'Austria')
+
+ assert_field 'consumerBillingAddress1', 'Daham 99'
+ assert_field 'consumerBillingZipCode', '8010'
+ assert_field 'consumerBillingCity', 'Graz'
+ assert_field 'consumerBillingState', 'Steiermark'
+ assert_field 'consumerBillingCountry', 'AT'
+
+ @helper.shipping_address(:first_name => 'Arnold',
+ :last_name => 'Schwarzenegger',
+ :address1 => 'Broadway 128',
+ :city => 'Los Angeles',
+ :state => 'NY',
+ :country => 'USA',
+ :zip => '10890',
+ :phone => '192634520',
+ :fax => '1926345202')
+
+ assert_field 'consumerShippingFirstName', 'Arnold'
+ assert_field 'consumerShippingLastName', 'Schwarzenegger'
+ assert_field 'consumerShippingAddress1', 'Broadway 128'
+ assert_field 'consumerShippingZipCode', '10890'
+ assert_field 'consumerShippingCity', 'Los Angeles'
+ assert_field 'consumerShippingState', 'NY'
+ assert_field 'consumerShippingCountry', 'US'
+ assert_field 'consumerShippingPhone', '192634520'
+ assert_field 'consumerShippingFax', '1926345202'
+
+ end
+
+end
diff --git a/test/unit/integrations/ipay88_module_test.rb b/test/unit/integrations/ipay88_module_test.rb
index 3125714060c..005ad4792f1 100644
--- a/test/unit/integrations/ipay88_module_test.rb
+++ b/test/unit/integrations/ipay88_module_test.rb
@@ -10,4 +10,8 @@ def test_return_method
def test_service_url
assert_equal "https://www.mobile88.com/epayment/entry.asp", Ipay88.service_url
end
+
+ def test_requery_url
+ assert_equal "https://www.mobile88.com/epayment/enquiry.asp", Ipay88.requery_url
+ end
end
diff --git a/test/unit/integrations/notifications/bit_pay_notification_test.rb b/test/unit/integrations/notifications/bit_pay_notification_test.rb
index 076c83eb8ca..5f55c145570 100644
--- a/test/unit/integrations/notifications/bit_pay_notification_test.rb
+++ b/test/unit/integrations/notifications/bit_pay_notification_test.rb
@@ -9,23 +9,61 @@ def setup
def test_accessors
assert @bit_pay.complete?
- assert_equal "complete", @bit_pay.status
- assert_equal "w1GRw1q86WPSUlT1r2cGsCZffrUM-KqT9fMFnbC9jo=", @bit_pay.transaction_id
- assert_equal 0.0083, @bit_pay.btcPrice
+ assert_equal "Completed", @bit_pay.status
+ assert_equal "98kui1gJ7FocK41gUaBZxG", @bit_pay.transaction_id
+ assert_equal 10.00, @bit_pay.gross
assert_equal "USD", @bit_pay.currency
assert_equal 1370539476654, @bit_pay.received_at
+ assert_equal 123, @bit_pay.item_id
+ end
+
+ def test_invalid_data
+ hash = JSON.parse(http_raw_data)
+ @bit_pay = BitPay::Notification.new('{"invalid":json}')
+
+ assert @bit_pay.params.empty?
+ end
+
+ def test_item_id_invalid_json
+ hash = JSON.parse(http_raw_data)
+ @bit_pay = BitPay::Notification.new(hash.merge('posData' => 'Invalid JSON').to_json)
+
+ assert_nil @bit_pay.item_id
end
def test_compositions
- assert_equal "1", @bit_pay.amount
+ assert_equal Money.new(1000, 'USD'), @bit_pay.amount
+ end
+
+ def test_successful_acknowledgement
+ Net::HTTP.any_instance.expects(:request).returns(stub(:body => http_raw_data))
+ assert @bit_pay.acknowledge
+ end
+
+ def test_acknowledgement_error
+ Net::HTTP.any_instance.expects(:request).returns(stub(:body => '{"error":"Doesnt match"}'))
+ assert !@bit_pay.acknowledge
end
- def test_acknowledgement
- assert @bit_pay.acknowledge('foobar')
+ def test_acknowledgement_invalid_json
+ Net::HTTP.any_instance.expects(:request).returns(stub(:body => '{invalid json'))
+ assert !@bit_pay.acknowledge
end
private
def http_raw_data
- "id=w1GRw1q86WPSUlT1r2cGsCZffrUM-KqT9fMFnbC9jo=&orderID=123&url=https://bitpay.com/invoice/w1GRw1q86WPSUlT1r2cGsCZffrUM-KqT9fMFnbC9jo=&status=complete&btcPrice=0.0083&price=1¤cy=USD&invoiceTime=1370539476654&expirationTime=1370540376654¤tTime=1370539573956&posData=foobar"
+ {
+ "id"=>"98kui1gJ7FocK41gUaBZxG",
+ "orderID"=>"123",
+ "url"=>"https://bitpay.com/invoice/98kui1gJ7FocK41gUaBZxG",
+ "status"=>"complete",
+ "btcPrice"=>"0.0295",
+ "price"=>"10.00",
+ "currency"=>"USD",
+ "invoiceTime"=>"1370539476654",
+ "expirationTime"=>"1370540376654",
+ "currentTime"=>"1370539573956",
+ "posData" => '{"orderId":123}'
+ }.to_json
end
end
diff --git a/test/unit/integrations/notifications/ipay88_notification_test.rb b/test/unit/integrations/notifications/ipay88_notification_test.rb
new file mode 100644
index 00000000000..80b89bfc78f
--- /dev/null
+++ b/test/unit/integrations/notifications/ipay88_notification_test.rb
@@ -0,0 +1,107 @@
+require 'test_helper'
+
+class Ipay88NotificationTest < Test::Unit::TestCase
+ include ActiveMerchant::Billing::Integrations
+
+ def setup
+ @ipay88 = build_notification(http_raw_data)
+ end
+
+ def test_accessors
+ assert_equal "ipay88merchcode", @ipay88.account
+ assert_equal 6, @ipay88.payment
+ assert_equal "order-500", @ipay88.item_id
+ assert_equal "5.00", @ipay88.gross
+ assert_equal "MYR", @ipay88.currency
+ assert_equal "Remarkable", @ipay88.remark
+ assert_equal "12345", @ipay88.transaction_id
+ assert_equal "auth123", @ipay88.auth_code
+ assert_equal "Completed", @ipay88.status
+ assert_equal "Invalid merchant", @ipay88.error
+ assert_equal "bPlMszCBwxlfGX9ZkgmSfT+OeLQ=", @ipay88.signature
+ end
+
+ def test_secure_request
+ assert @ipay88.secure?
+ end
+
+ def test_success
+ assert @ipay88.success?
+ end
+
+ def test_insecure_request
+ assert !build_notification(http_raw_data(:invalid_sig)).secure?
+ end
+
+ def test_acknowledge
+ params = parameterize(payload)
+ @ipay88.expects(:ssl_post).with(Ipay88.requery_url, params,
+ { "Content-Length" => params.size.to_s, "User-Agent" => "Active Merchant -- http://activemerchant.org" }
+ ).returns("00")
+
+ assert @ipay88.acknowledge
+ end
+
+ def test_unsuccessful_acknowledge_due_to_signature
+ ipay = build_notification(http_raw_data(:invalid_sig))
+ assert !ipay.acknowledge
+ end
+
+ def test_unsuccessful_acknowledge_due_to_requery
+ params = parameterize(payload)
+ @ipay88.expects(:ssl_post).with(Ipay88.requery_url, params,
+ { "Content-Length" => params.size.to_s, "User-Agent" => "Active Merchant -- http://activemerchant.org" }
+ ).returns("Invalid parameters")
+ assert !@ipay88.acknowledge
+ end
+
+ def test_unsuccessful_acknowledge_due_to_payment_failed
+ params = parameterize(payload)
+ ipay = build_notification(http_raw_data(:payment_failed))
+ assert !ipay.acknowledge
+ end
+
+ def test_unsuccessful_acknowledge_due_to_missing_amount
+ ipay = build_notification(http_raw_data(:missing_amount))
+ assert !ipay.acknowledge
+ end
+
+ private
+ def http_raw_data(mode=:success)
+ base = { "MerchantCode" => "ipay88merchcode",
+ "PaymentId" => 6,
+ "RefNo" => "order-500",
+ "Amount" => "5.00",
+ "Currency" => "MYR",
+ "Remark" => "Remarkable",
+ "TransId" => "12345",
+ "AuthCode" => "auth123",
+ "Status" => 1,
+ "ErrDesc" => "Invalid merchant" }
+
+ case mode
+ when :success
+ parameterize(base.merge("Signature" => "bPlMszCBwxlfGX9ZkgmSfT+OeLQ="))
+ when :invalid_sig
+ parameterize(base.merge("Signature" => "hacked"))
+ when :payment_failed
+ parameterize(base.merge("Status" => 0, "Signature" => "p8nXYcl/wytpNMzsf31O/iu/2EU="))
+ when :missing_amount
+ parameterize(base.except("Amount"))
+ else
+ ""
+ end
+ end
+
+ def payload
+ { "MerchantCode" => "ipay88merchcode", "RefNo" => "order-500", "Amount" => "5.00" }
+ end
+
+ def parameterize(params)
+ params.reject{|k, v| v.blank?}.keys.sort.collect { |key| "#{key}=#{CGI.escape(params[key].to_s)}" }.join("&")
+ end
+
+ def build_notification(data)
+ Ipay88::Notification.new(data, :credential2 => "apple")
+ end
+end
diff --git a/test/unit/integrations/notifications/notification_test.rb b/test/unit/integrations/notifications/notification_test.rb
index 0e9d4a759ed..671a5e5da9e 100644
--- a/test/unit/integrations/notifications/notification_test.rb
+++ b/test/unit/integrations/notifications/notification_test.rb
@@ -16,6 +16,8 @@ def test_parse
assert_equal "confirmed", @notification.params['address_status']
assert_equal "EVMXCLDZJV77Q", @notification.params['payer_id']
assert_equal "Completed", @notification.params['payment_status']
+ assert_equal "ru", @notification.params['yamoney-lang']
+ assert_equal '', @notification.params['empty_params']
assert_equal CGI.unescape("15%3A23%3A54+Apr+15%2C+2005+PDT"), @notification.params['payment_date']
end
@@ -45,10 +47,10 @@ def test_valid_sender_always_true_when_no_ips
private
def http_raw_data
- "mc_gross=500.00&address_status=confirmed&payer_id=EVMXCLDZJV77Q&tax=0.00&address_street=164+Waverley+Street&payment_date=15%3A23%3A54+Apr+15%2C+2005+PDT&payment_status=Completed&address_zip=K2P0V6&first_name=Tobias&mc_fee=15.05&address_country_code=CA&address_name=Tobias+Luetke¬ify_version=1.7&custom=&payer_status=unverified&business=tobi%40leetsoft.com&address_country=Canada&address_city=Ottawa&quantity=1&payer_email=tobi%40snowdevil.ca&verify_sign=AEt48rmhLYtkZ9VzOGAtwL7rTGxUAoLNsuf7UewmX7UGvcyC3wfUmzJP&txn_id=6G996328CK404320L&payment_type=instant&last_name=Luetke&address_state=Ontario&receiver_email=tobi%40leetsoft.com&payment_fee=&receiver_id=UQ8PDYXJZQD9Y&txn_type=web_accept&item_name=Store+Purchase&mc_currency=CAD&item_number=&test_ipn=1&payment_gross=&shipping=0.00"
+ "mc_gross=500.00&address_status=confirmed&payer_id=EVMXCLDZJV77Q&tax=0.00&address_street=164+Waverley+Street&payment_date=15%3A23%3A54+Apr+15%2C+2005+PDT&payment_status=Completed&address_zip=K2P0V6&first_name=Tobias&mc_fee=15.05&address_country_code=CA&address_name=Tobias+Luetke¬ify_version=1.7&custom=&payer_status=unverified&business=tobi%40leetsoft.com&address_country=Canada&address_city=Ottawa&quantity=1&payer_email=tobi%40snowdevil.ca&verify_sign=AEt48rmhLYtkZ9VzOGAtwL7rTGxUAoLNsuf7UewmX7UGvcyC3wfUmzJP&txn_id=6G996328CK404320L&payment_type=instant&last_name=Luetke&address_state=Ontario&receiver_email=tobi%40leetsoft.com&payment_fee=&receiver_id=UQ8PDYXJZQD9Y&txn_type=web_accept&item_name=Store+Purchase&mc_currency=CAD&item_number=&test_ipn=1&payment_gross=&shipping=0.00&yamoney-lang=ru&empty_params="
end
def http_raw_data_with_period
- "mc_gross=500.00&address_status=confirmed&payer_id=EVMXCLDZJV77Q&tax=0.00&address_street=164+Waverley+Street&payment_date=15%3A23%3A54+Apr+15%2C+2005+PDT&payment_status=Completed&address_zip=K2P0V6&first_name=Tobias&mc_fee=15.05&address_country_code=CA&address_name=Tobias+Luetke¬ify_version=1.7&custom=&payer_status=unverified&business=tobi%40leetsoft.com&address_country=Canada&address_city=Ottawa&quantity=1&payer_email=tobi%40snowdevil.ca&verify_sign=AEt48rmhLYtkZ9VzOGAtwL7rTGxUAoLNsuf7UewmX7UGvcyC3wfUmzJP&txn_id=6G996328CK404320L&payment_type=instant&last_name=Luetke&address_state=Ontario&receiver_email=tobi%40leetsoft.com&payment_fee=&receiver_id=UQ8PDYXJZQD9Y&txn_type=web_accept&item_name=Store+Purchase&mc_currency=CAD&item_number=&test_ipn=1&payment_gross=&shipping=0.00&checkout.x=clicked"
+ "mc_gross=500.00&address_status=confirmed&payer_id=EVMXCLDZJV77Q&tax=0.00&address_street=164+Waverley+Street&payment_date=15%3A23%3A54+Apr+15%2C+2005+PDT&payment_status=Completed&address_zip=K2P0V6&first_name=Tobias&mc_fee=15.05&address_country_code=CA&address_name=Tobias+Luetke¬ify_version=1.7&custom=&payer_status=unverified&business=tobi%40leetsoft.com&address_country=Canada&address_city=Ottawa&quantity=1&payer_email=tobi%40snowdevil.ca&verify_sign=AEt48rmhLYtkZ9VzOGAtwL7rTGxUAoLNsuf7UewmX7UGvcyC3wfUmzJP&txn_id=6G996328CK404320L&payment_type=instant&last_name=Luetke&address_state=Ontario&receiver_email=tobi%40leetsoft.com&payment_fee=&receiver_id=UQ8PDYXJZQD9Y&txn_type=web_accept&item_name=Store+Purchase&mc_currency=CAD&item_number=&test_ipn=1&payment_gross=&shipping=0.00&checkout.x=clicked&yamoney-lang=ru&empty_params="
end
end
diff --git a/test/unit/integrations/notifications/payu_in_notification_test.rb b/test/unit/integrations/notifications/payu_in_notification_test.rb
index 7ca50e350e1..94f1a6772ce 100644
--- a/test/unit/integrations/notifications/payu_in_notification_test.rb
+++ b/test/unit/integrations/notifications/payu_in_notification_test.rb
@@ -4,7 +4,7 @@ class PayuInNotificationTest < Test::Unit::TestCase
include ActiveMerchant::Billing::Integrations
def setup
- @payu = PayuIn::Notification.new(http_raw_data, :credential1 => 'C0Dr8m', :credential2 => '3sf0jURk')
+ @payu = PayuIn::Notification.new(http_raw_data, :credential1 => 'merchant_id', :credential2 => 'secret')
end
def test_accessors
@@ -19,13 +19,13 @@ def test_accessors
assert_equal true, @payu.amount_ok?(BigDecimal.new('10.00'),BigDecimal.new('0.00'))
assert_equal "CC", @payu.type
assert_equal "4ba4afe87f7e73468f2a", @payu.invoice
- assert_equal "C0Dr8m", @payu.account
+ assert_equal "merchant_id", @payu.account
assert_equal "0.00", @payu.discount
assert_equal "test@example.com", @payu.customer_email
assert_equal "1234567890", @payu.customer_phone
assert_equal "Payu-Admin", @payu.customer_first_name
assert_equal "", @payu.customer_last_name
- assert_equal "ef0c1b509a42b802a4938c25dc9bb9efe40b75a7dfb8bde1a6f126fa1f86cee264c5e5a17e87db85150d6d8912eafda838416e669712f1989dcb9cbdb8c24219", @payu.checksum
+ assert_equal "d6a5544072d036dc422d1c6393a8da75233d5e30ffc848f11682f121d67cd80c0d4fed1067b99918b5a377b7dcf1c8c9c79975abdf9f444692b35bf34d494105", @payu.checksum
assert_equal "E000", @payu.message
assert_equal true, @payu.checksum_ok?
end
@@ -38,12 +38,8 @@ def test_acknowledgement
assert @payu.acknowledge
end
- def test_respond_to_acknowledge
- assert @payu.respond_to?(:acknowledge)
- end
-
private
def http_raw_data
- "mihpayid=403993715508030204&mode=CC&status=success&unmappedstatus=captured&key=C0Dr8m&txnid=4ba4afe87f7e73468f2a&amount=10.00&discount=0.00&addedon=2013-05-10 18 32 30&productinfo=Product Info&firstname=Payu-Admin&lastname=&address1=&address2=&city=&state=&country=&zipcode=&email=test@example.com&phone=1234567890&udf1=&udf2=&udf3=&udf4=&udf5=&udf6=&udf7=&udf8=&udf9=&udf10=&hash=ef0c1b509a42b802a4938c25dc9bb9efe40b75a7dfb8bde1a6f126fa1f86cee264c5e5a17e87db85150d6d8912eafda838416e669712f1989dcb9cbdb8c24219&field1=313069903923&field2=999999&field3=59117331831301&field4=-1&field5=&field6=&field7=&field8=&PG_TYPE=HDFC&bank_ref_num=59117331831301&bankcode=CC&error=E000&cardnum=512345XXXXXX2346&cardhash=766f0227cc4b4c5f773a04cb31d8d1c5be071dd8d08fe365ecf5e2e5c947546d"
+ "mihpayid=403993715508030204&mode=CC&status=success&unmappedstatus=captured&key=merchant_id&txnid=4ba4afe87f7e73468f2a&amount=10.00&discount=0.00&addedon=2013-05-10 18 32 30&productinfo=Product Info&firstname=Payu-Admin&lastname=&address1=&address2=&city=&state=&country=&zipcode=&email=test@example.com&phone=1234567890&udf1=&udf2=&udf3=&udf4=&udf5=&udf6=&udf7=&udf8=&udf9=&udf10=&hash=d6a5544072d036dc422d1c6393a8da75233d5e30ffc848f11682f121d67cd80c0d4fed1067b99918b5a377b7dcf1c8c9c79975abdf9f444692b35bf34d494105&field1=313069903923&field2=999999&field3=59117331831301&field4=-1&field5=&field6=&field7=&field8=&PG_TYPE=HDFC&bank_ref_num=59117331831301&bankcode=CC&error=E000&cardnum=512345XXXXXX2346&cardhash=766f0227cc4b4c5f773a04cb31d8d1c5be071dd8d08fe365ecf5e2e5c947546d"
end
end
diff --git a/test/unit/integrations/notifications/payu_in_paisa_notification_test.rb b/test/unit/integrations/notifications/payu_in_paisa_notification_test.rb
index 19601829da5..40b749986ce 100644
--- a/test/unit/integrations/notifications/payu_in_paisa_notification_test.rb
+++ b/test/unit/integrations/notifications/payu_in_paisa_notification_test.rb
@@ -4,7 +4,7 @@ class PayuInPaisaNotificationTest < Test::Unit::TestCase
include ActiveMerchant::Billing::Integrations
def setup
- @payu = PayuInPaisa::Notification.new(http_raw_data, :credential1 => 'C0Dr8m', :credential2 => '3sf0jURk')
+ @payu = PayuInPaisa::Notification.new(http_raw_data, :credential1 => 'merchant_id', :credential2 => 'secret')
end
def test_accessors
@@ -19,13 +19,13 @@ def test_accessors
assert_equal true, @payu.amount_ok?(BigDecimal.new('10.00'),BigDecimal.new('0.00'))
assert_equal "CC", @payu.type
assert_equal "4ba4afe87f7e73468f2a", @payu.invoice
- assert_equal "C0Dr8m", @payu.account
+ assert_equal "merchant_id", @payu.account
assert_equal "0.00", @payu.discount
assert_equal "test@example.com", @payu.customer_email
assert_equal "1234567890", @payu.customer_phone
assert_equal "Payu-Admin", @payu.customer_first_name
assert_equal "", @payu.customer_last_name
- assert_equal "e35f67dc7232d12caa28b16ba31b509f62bdea1e930bb6766a4f71036cc1af34debb8afc0fdd89be50f0604c1e6bca7209dfffe6b3a893c575492edcab3444ee", @payu.checksum
+ assert_equal checksum, @payu.checksum
assert_equal "E000", @payu.message
assert_equal true, @payu.checksum_ok?
end
@@ -38,16 +38,16 @@ def test_acknowledgement
assert @payu.acknowledge
end
- def test_respond_to_acknowledge
- assert @payu.respond_to?(:acknowledge)
- end
-
def test_item_id_gives_the_original_item_id
assert 'original_item_id', @payu.item_id
end
private
def http_raw_data
- "mihpayid=403993715508030204&mode=CC&status=success&unmappedstatus=captured&key=C0Dr8m&txnid=4ba4afe87f7e73468f2a&amount=10.00&discount=0.00&addedon=2013-05-10 18 32 30&productinfo=Product Info&firstname=Payu-Admin&lastname=&address1=&address2=&city=&state=&country=&zipcode=&email=test@example.com&phone=1234567890&udf1=&udf2=original_item_id&udf3=&udf4=&udf5=&udf6=&udf7=&udf8=&udf9=&udf10=&hash=e35f67dc7232d12caa28b16ba31b509f62bdea1e930bb6766a4f71036cc1af34debb8afc0fdd89be50f0604c1e6bca7209dfffe6b3a893c575492edcab3444ee&field1=313069903923&field2=999999&field3=59117331831301&field4=-1&field5=&field6=&field7=&field8=&PG_TYPE=HDFC&bank_ref_num=59117331831301&bankcode=CC&error=E000&cardnum=512345XXXXXX2346&cardhash=766f0227cc4b4c5f773a04cb31d8d1c5be071dd8d08fe365ecf5e2e5c947546d"
+ "mihpayid=403993715508030204&mode=CC&status=success&unmappedstatus=captured&key=merchant_id&txnid=4ba4afe87f7e73468f2a&amount=10.00&discount=0.00&addedon=2013-05-10 18 32 30&productinfo=Product Info&firstname=Payu-Admin&lastname=&address1=&address2=&city=&state=&country=&zipcode=&email=test@example.com&phone=1234567890&udf1=&udf2=original_item_id&udf3=&udf4=&udf5=&udf6=&udf7=&udf8=&udf9=&udf10=&hash=#{checksum}&field1=313069903923&field2=999999&field3=59117331831301&field4=-1&field5=&field6=&field7=&field8=&PG_TYPE=HDFC&bank_ref_num=59117331831301&bankcode=CC&error=E000&cardnum=512345XXXXXX2346&cardhash=766f0227cc4b4c5f773a04cb31d8d1c5be071dd8d08fe365ecf5e2e5c947546d"
+ end
+
+ def checksum
+ Digest::SHA512.hexdigest("secret|success|||||||||original_item_id||test@example.com|Payu-Admin|Product Info|10.00|4ba4afe87f7e73468f2a|merchant_id")
end
end
diff --git a/test/unit/integrations/notifications/valitor_notification_test.rb b/test/unit/integrations/notifications/valitor_notification_test.rb
index a49502e4108..4775abc9acb 100644
--- a/test/unit/integrations/notifications/valitor_notification_test.rb
+++ b/test/unit/integrations/notifications/valitor_notification_test.rb
@@ -33,6 +33,12 @@ def test_accessors
assert !@notification.test?
end
+
+ def test_comma_delimited_notification
+ @notification = Valitor::Notification.new(http_raw_query_with_comma_delimited_currency)
+
+ assert_equal "25.99", @notification.gross
+ end
def test_acknowledge
valid = Valitor.notification(http_raw_query, :credential2 => 'password')
@@ -54,4 +60,8 @@ def test_test_mode
def http_raw_query
"Kortategund=VISA&KortnumerSidustu=9999&Dagsetning=21.01.2011&Heimildarnumer=123450&Faerslunumer=FÆRSLUNR: 0026237&VefverslunSalaID=2b969de3-6928-4fa7-a0d6-6dec63fec5c3&Tilvisunarnumer=order684afbb93730db2492a8fa2f3fedbcb9&RafraenUndirskriftSvar=03d859813eff711d6c8667b0caf5f5a5&Upphaed=100&Nafn=NAME&Heimilisfang=123 ADDRESS&Postnumer=98765&Stadur=CITY&Land=COUNTRY&Tolvupostfang=EMAIL@EXAMPLE.COM&Athugasemdir=COMMENTS&LeyfirEndurtoku="
end
+
+ def http_raw_query_with_comma_delimited_currency
+ "Kortategund=VISA&KortnumerSidustu=9999&Dagsetning=21.01.2011&Heimildarnumer=123450&Faerslunumer=FÆRSLUNR: 0026237&VefverslunSalaID=2b969de3-6928-4fa7-a0d6-6dec63fec5c3&Tilvisunarnumer=order684afbb93730db2492a8fa2f3fedbcb9&RafraenUndirskriftSvar=03d859813eff711d6c8667b0caf5f5a5&Upphaed=25,99&Nafn=NAME&Heimilisfang=123 ADDRESS&Postnumer=98765&Stadur=CITY&Land=COUNTRY&Tolvupostfang=EMAIL@EXAMPLE.COM&Athugasemdir=COMMENTS&LeyfirEndurtoku="
+ end
end
diff --git a/test/unit/integrations/notifications/wirecard_checkout_page_notification_test.rb b/test/unit/integrations/notifications/wirecard_checkout_page_notification_test.rb
new file mode 100644
index 00000000000..8beedfb19ad
--- /dev/null
+++ b/test/unit/integrations/notifications/wirecard_checkout_page_notification_test.rb
@@ -0,0 +1,33 @@
+require 'test_helper'
+
+class WirecardCheckoutPageNotificationTest < Test::Unit::TestCase
+ include ActiveMerchant::Billing::Integrations
+
+ def setup
+ @options = fixtures(:wirecard_checkout_page)
+ @wirecard_checkout_page = WirecardCheckoutPage::Notification.new(http_raw_data, @options)
+ end
+
+ def test_accessors
+ @wirecard_checkout_page.acknowledge
+ assert_equal nil, @wirecard_checkout_page.message
+ assert @wirecard_checkout_page.complete?
+ assert_equal "13", @wirecard_checkout_page.item_id
+ assert_equal "110.99", @wirecard_checkout_page.gross
+ assert_equal "EUR", @wirecard_checkout_page.currency
+ assert_equal "IDL", @wirecard_checkout_page.paymentType
+ end
+
+ def test_send_acknowledgement
+ assert_equal '', @wirecard_checkout_page.response
+ end
+
+ def test_respond_to_acknowledge
+ assert @wirecard_checkout_page.respond_to?(:acknowledge)
+ end
+
+ private
+ def http_raw_data
+ "amount=110.99¤cy=EUR&paymentType=IDL&financialInstitution=INGBANK&language=de&orderNumber=9882408&paymentState=SUCCESS&utf8=%E2%9C%93&xActiveMerchantOrderId=13&consumerIpAddress=192.168.201.181&consumerUserAgent=Mozilla%2F5.0+%28X11%3B+Ubuntu%3B+Linux+x86_64%3B+rv%3A24.0%29+Gecko%2F20100101+Firefox%2F24.0&commit=Jetzt+bezahlen&idealConsumerName=Test+C%C3%B6ns%C3%BCmer+Utl%C3%B8psdato&idealConsumerBIC=RABONL2U&idealConsumerCity=RABONL2U&idealConsumerIBAN=NL17RABO0213698412&idealConsumerAccountNumber=NL17RABO0213698412&gatewayReferenceNumber=DGW_9882408_RN&gatewayContractNumber=DemoContractNumber123&avsResponseCode=X&avsResponseMessage=Demo+AVS+ResultMessage&responseFingerprintOrder=amount%2Ccurrency%2CpaymentType%2CfinancialInstitution%2Clanguage%2CorderNumber%2CpaymentState%2Cutf8%2CxActiveMerchantOrderId%2CconsumerIpAddress%2CconsumerUserAgent%2Ccommit%2CidealConsumerName%2CidealConsumerBIC%2CidealConsumerCity%2CidealConsumerIBAN%2CidealConsumerAccountNumber%2CgatewayReferenceNumber%2CgatewayContractNumber%2CavsResponseCode%2CavsResponseMessage%2Csecret%2CresponseFingerprintOrder&responseFingerprint=a15a4fceefcab5a41380f97079180d55"
+ end
+end
diff --git a/test/unit/integrations/payu_in_module_test.rb b/test/unit/integrations/payu_in_module_test.rb
index f563f4a425b..53441994f9c 100644
--- a/test/unit/integrations/payu_in_module_test.rb
+++ b/test/unit/integrations/payu_in_module_test.rb
@@ -5,8 +5,8 @@ class PayuInModuleTest < Test::Unit::TestCase
def setup
ActiveMerchant::Billing::Base.integration_mode = :test
- @merchant_id = 'C0Dr8m'
- @secret_key = '3sf0jURk'
+ @merchant_id = 'merchant_id'
+ @secret_key = 'secret'
end
def test_service_url_method
@@ -26,7 +26,8 @@ def test_notification_method
end
def test_checksum_method
- payu_load = "4ba4afe87f7e73468f2a|10.00|Product Info|Payu-Admin|test@example.com||||||||||"
- assert_equal "cd324f64891b07d95492a2fd80ae469092e302faa3d3df5ba1b829936fd7497b6e89c3e48fd70e2a131cdd4f17d14bc20f292e9408650c085bc3bedb32f44266", PayuIn.checksum(@merchant_id, @secret_key, payu_load)
+ payu_load = "order_id|10.00|Product Info|Payu-Admin|test@example.com||||||||||"
+ checksum = Digest::SHA512.hexdigest([@merchant_id, payu_load, @secret_key].join("|"))
+ assert_equal checksum, PayuIn.checksum(@merchant_id, @secret_key, payu_load.split("|", -1))
end
end
diff --git a/test/unit/integrations/payu_in_paisa_module_test.rb b/test/unit/integrations/payu_in_paisa_module_test.rb
index 12e63f431b3..00e3235227b 100644
--- a/test/unit/integrations/payu_in_paisa_module_test.rb
+++ b/test/unit/integrations/payu_in_paisa_module_test.rb
@@ -9,17 +9,17 @@ def setup
def test_service_url_method
ActiveMerchant::Billing::Base.integration_mode = :test
- assert_equal "https://test.payu.in/_payment.php", PayuIn.service_url
+ assert_equal "https://test.payu.in/_payment.php", PayuInPaisa.service_url
ActiveMerchant::Billing::Base.integration_mode = :production
- assert_equal "https://secure.payu.in/_payment.php", PayuIn.service_url
+ assert_equal "https://secure.payu.in/_payment.php", PayuInPaisa.service_url
end
def test_return_method
- assert_instance_of PayuIn::Return, PayuIn.return('name=foo', {})
+ assert_instance_of PayuInPaisa::Return, PayuInPaisa.return('name=foo', {})
end
def test_notification_method
- assert_instance_of PayuIn::Notification, PayuIn.notification('name=foo', {})
+ assert_instance_of PayuInPaisa::Notification, PayuInPaisa.notification('name=foo', {})
end
end
diff --git a/test/unit/integrations/returns/ipay88_return_test.rb b/test/unit/integrations/returns/ipay88_return_test.rb
index efae6dae385..e797905ae39 100644
--- a/test/unit/integrations/returns/ipay88_return_test.rb
+++ b/test/unit/integrations/returns/ipay88_return_test.rb
@@ -4,103 +4,23 @@ class Ipay88ReturnTest < Test::Unit::TestCase
include ActiveMerchant::Billing::Integrations
def setup
- @ipay88 = build_return(http_raw_data)
+ @ipay = Ipay88::Return.new(http_raw_data, :credential2 => 'secret')
end
- def test_accessors
- assert_equal "ipay88merchcode", @ipay88.account
- assert_equal 6, @ipay88.payment
- assert_equal "order-500", @ipay88.order
- assert_equal "5.00", @ipay88.amount
- assert_equal "MYR", @ipay88.currency
- assert_equal "Remarkable", @ipay88.remark
- assert_equal "12345", @ipay88.transaction
- assert_equal "auth123", @ipay88.auth_code
- assert_equal "1", @ipay88.status
- assert_equal "Invalid merchant", @ipay88.error
- assert_equal "bPlMszCBwxlfGX9ZkgmSfT+OeLQ=", @ipay88.signature
+ def test_success?
+ assert @ipay.success?
end
- def test_secure_request
- assert @ipay88.secure?
+ def test_message_returns_error_description
+ assert_equal 'Customer Cancel Transaction', @ipay.message
end
- def test_insecure_request
- assert !build_return(http_raw_data(:invalid_sig)).secure?
- end
-
- def test_successful_return
- params = parameterize(payload)
- Ipay88::Return.any_instance.expects(:ssl_post).with(Ipay88.service_url, params,
- { "Content-Length" => params.size.to_s, "User-Agent" => "Active Merchant -- http://activemerchant.org" }
- ).returns("00")
-
- assert @ipay88.success?
- end
-
- def test_unsuccessful_return_due_to_signature
- ipay = build_return(http_raw_data(:invalid_sig))
- assert !ipay.success?
- end
-
- def test_unsuccessful_return_due_to_requery
- params = parameterize(payload)
- Ipay88::Return.any_instance.expects(:ssl_post).with(Ipay88.service_url, params,
- { "Content-Length" => params.size.to_s, "User-Agent" => "Active Merchant -- http://activemerchant.org" }
- ).returns("Invalid parameters")
- assert !@ipay88.success?
- end
-
- def test_unsuccessful_return_due_to_payment_failed
- params = parameterize(payload)
- Ipay88::Return.any_instance.expects(:ssl_post).with(Ipay88.service_url, params,
- { "Content-Length" => params.size.to_s, "User-Agent" => "Active Merchant -- http://activemerchant.org" }
- ).returns("00")
- ipay = build_return(http_raw_data(:payment_failed))
- assert !ipay.success?
- end
-
- def test_unsuccessful_return_due_to_missing_amount
- ipay = build_return(http_raw_data(:missing_amount))
- assert !ipay.success?
+ def test_cancelled
+ assert @ipay.cancelled?
end
private
- def http_raw_data(mode=:success)
- base = { "MerchantCode" => "ipay88merchcode",
- "PaymentId" => 6,
- "RefNo" => "order-500",
- "Amount" => "5.00",
- "Currency" => "MYR",
- "Remark" => "Remarkable",
- "TransId" => "12345",
- "AuthCode" => "auth123",
- "Status" => 1,
- "ErrDesc" => "Invalid merchant" }
-
- case mode
- when :success
- parameterize(base.merge("Signature" => "bPlMszCBwxlfGX9ZkgmSfT+OeLQ="))
- when :invalid_sig
- parameterize(base.merge("Signature" => "hacked"))
- when :payment_failed
- parameterize(base.merge("Status" => 0, "Signature" => "p8nXYcl/wytpNMzsf31O/iu/2EU="))
- when :missing_amount
- parameterize(base.except("Amount"))
- else
- ""
- end
- end
-
- def payload
- { "MerchantCode" => "ipay88merchcode", "RefNo" => "order-500", "Amount" => "5.00" }
- end
-
- def parameterize(params)
- params.reject{|k, v| v.blank?}.keys.sort.collect { |key| "#{key}=#{CGI.escape(params[key].to_s)}" }.join("&")
- end
-
- def build_return(data)
- Ipay88::Return.new(data, :credential2 => "apple")
+ def http_raw_data
+ "Amount=0.10&AuthCode=12345678&Currency=USD&ErrDesc=Customer Cancel Transaction&MerchantCode=M00001&PaymentId=1&RefNo=10000001&Remark=&Signature=RWAehzFtiNCKQWpXheazrCF33J4%3D&Status=1&TransId=T123456789"
end
end
diff --git a/test/unit/integrations/returns/payu_in_paisa_return_test.rb b/test/unit/integrations/returns/payu_in_paisa_return_test.rb
index 174a682e7c2..97baca37ec0 100644
--- a/test/unit/integrations/returns/payu_in_paisa_return_test.rb
+++ b/test/unit/integrations/returns/payu_in_paisa_return_test.rb
@@ -4,11 +4,11 @@ class PayuInPaisaReturnTest < Test::Unit::TestCase
include ActiveMerchant::Billing::Integrations
def setup
- @payu = PayuInPaisa::Return.new(http_raw_data_success, :credential1 => 'C0Dr8m', :credential2 => '3sf0jURk')
+ @payu = PayuInPaisa::Return.new(http_raw_data_success, :credential1 => 'merchant_id', :credential2 => 'secret')
end
def setup_failed_return
- @payu = PayuInPaisa::Return.new(http_raw_data_failure, :credential1 => 'C0Dr8m', :credential2 => '3sf0jURk')
+ @payu = PayuInPaisa::Return.new(http_raw_data_failure, :credential1 => 'merchant_id', :credential2 => 'secret')
end
def test_success
@@ -38,7 +38,7 @@ def test_return_has_notification
assert_equal 'CC', @payu.notification.type
assert_equal 'INR', notification.currency
assert_equal '4ba4afe87f7e73468f2a', notification.invoice
- assert_equal 'C0Dr8m', notification.account
+ assert_equal 'merchant_id', notification.account
assert_equal '10.00', notification.gross
assert_equal '0.00', notification.discount
assert_equal nil, notification.offer_description
@@ -48,7 +48,7 @@ def test_return_has_notification
assert_equal 'Payu-Admin', notification.customer_first_name
assert_equal '', notification.customer_last_name
assert_equal ["", "original_item_id", "", "", "", "", "", "", "", ""], notification.user_defined
- assert_equal "e35f67dc7232d12caa28b16ba31b509f62bdea1e930bb6766a4f71036cc1af34debb8afc0fdd89be50f0604c1e6bca7209dfffe6b3a893c575492edcab3444ee", notification.checksum
+ assert_equal checksum, notification.checksum
assert_equal 'E000', notification.message
assert notification.checksum_ok?
end
@@ -56,11 +56,15 @@ def test_return_has_notification
private
def http_raw_data_success
- "mihpayid=403993715508030204&mode=CC&status=success&unmappedstatus=captured&key=C0Dr8m&txnid=4ba4afe87f7e73468f2a&amount=10.00&discount=0.00&addedon=2013-05-10 18 32 30&productinfo=Product Info&firstname=Payu-Admin&lastname=&address1=&address2=&city=&state=&country=&zipcode=&email=test@example.com&phone=1234567890&udf1=&udf2=original_item_id&udf3=&udf4=&udf5=&udf6=&udf7=&udf8=&udf9=&udf10=&hash=e35f67dc7232d12caa28b16ba31b509f62bdea1e930bb6766a4f71036cc1af34debb8afc0fdd89be50f0604c1e6bca7209dfffe6b3a893c575492edcab3444ee&field1=313069903923&field2=999999&field3=59117331831301&field4=-1&field5=&field6=&field7=&field8=&PG_TYPE=HDFC&bank_ref_num=59117331831301&bankcode=CC&error=E000&cardnum=512345XXXXXX2346&cardhash=766f0227cc4b4c5f773a04cb31d8d1c5be071dd8d08fe365ecf5e2e5c947546d"
+ "mihpayid=403993715508030204&mode=CC&status=success&unmappedstatus=captured&key=merchant_id&txnid=4ba4afe87f7e73468f2a&amount=10.00&discount=0.00&addedon=2013-05-10 18 32 30&productinfo=Product Info&firstname=Payu-Admin&lastname=&address1=&address2=&city=&state=&country=&zipcode=&email=test@example.com&phone=1234567890&udf1=&udf2=original_item_id&udf3=&udf4=&udf5=&udf6=&udf7=&udf8=&udf9=&udf10=&hash=#{checksum}&field1=313069903923&field2=999999&field3=59117331831301&field4=-1&field5=&field6=&field7=&field8=&PG_TYPE=HDFC&bank_ref_num=59117331831301&bankcode=CC&error=E000&cardnum=512345XXXXXX2346&cardhash=766f0227cc4b4c5f773a04cb31d8d1c5be071dd8d08fe365ecf5e2e5c947546d"
end
def http_raw_data_failure
- "mihpayid=403993715508030204&mode=CC&status=failure&unmappedstatus=failed&key=C0Dr8m&txnid=8ae1034d1abf47fde1cf&amount=10.00&discount=0.00&addedon=2013-05-13 11:09:20&productinfo=Product Info&firstname=Payu-Admin&lastname=&address1=&address2=&city=&state=&country=&zipcode=&email=test@example.com&phone=1234567890&udf1=&udf2=&udf3=&udf4=&udf5=&udf6=&udf7=&udf8=&udf9=&udf10=&hash=65774f82abe64cec54be31107529b2a3eef8f6a3f97a8cb81e9769f4394b890b0e7171f8988c4df3684e7f9f337035d0fe09a844da4b76e68dd643e8ac5e5c63&field1=&field2=&field3=&field4=&field5=!ERROR!-GV00103-Invalid BrandError Code: GV00103&field6=&field7=&field8=failed in enrollment&PG_TYPE=HDFC&bank_ref_num=&bankcode=CC&error=E201&cardnum=411111XXXXXX1111&cardhash=49c73d6c44f27f7ac71b439de842f91e27fcbc3b9ce9dfbcbf1ce9a8fe790c17"
+ "mihpayid=403993715508030204&mode=CC&status=failure&unmappedstatus=failed&key=merchant_id&txnid=8ae1034d1abf47fde1cf&amount=10.00&discount=0.00&addedon=2013-05-13 11:09:20&productinfo=Product Info&firstname=Payu-Admin&lastname=&address1=&address2=&city=&state=&country=&zipcode=&email=test@example.com&phone=1234567890&udf1=&udf2=&udf3=&udf4=&udf5=&udf6=&udf7=&udf8=&udf9=&udf10=&hash=65774f82abe64cec54be31107529b2a3eef8f6a3f97a8cb81e9769f4394b890b0e7171f8988c4df3684e7f9f337035d0fe09a844da4b76e68dd643e8ac5e5c63&field1=&field2=&field3=&field4=&field5=!ERROR!-GV00103-Invalid BrandError Code: GV00103&field6=&field7=&field8=failed in enrollment&PG_TYPE=HDFC&bank_ref_num=&bankcode=CC&error=E201&cardnum=411111XXXXXX1111&cardhash=49c73d6c44f27f7ac71b439de842f91e27fcbc3b9ce9dfbcbf1ce9a8fe790c17"
+ end
+
+ def checksum
+ Digest::SHA512.hexdigest("secret|success|||||||||original_item_id||test@example.com|Payu-Admin|Product Info|10.00|4ba4afe87f7e73468f2a|merchant_id")
end
end
diff --git a/test/unit/integrations/returns/payu_in_return_test.rb b/test/unit/integrations/returns/payu_in_return_test.rb
index add0f355cfe..6e49d8f0e5d 100644
--- a/test/unit/integrations/returns/payu_in_return_test.rb
+++ b/test/unit/integrations/returns/payu_in_return_test.rb
@@ -4,11 +4,11 @@ class PayuInReturnTest < Test::Unit::TestCase
include ActiveMerchant::Billing::Integrations
def setup
- @payu = PayuIn::Return.new(http_raw_data_success, :credential1 => 'C0Dr8m', :credential2 => '3sf0jURk')
+ @payu = PayuIn::Return.new(http_raw_data_success, :credential1 => 'merchant_id', :credential2 => 'secret')
end
def setup_failed_return
- @payu = PayuIn::Return.new(http_raw_data_failure, :credential1 => 'C0Dr8m', :credential2 => '3sf0jURk')
+ @payu = PayuIn::Return.new(http_raw_data_failure, :credential1 => 'merchant_id', :credential2 => 'secret')
end
def test_success
@@ -38,7 +38,7 @@ def test_return_has_notification
assert_equal 'CC', @payu.notification.type
assert_equal 'INR', notification.currency
assert_equal '4ba4afe87f7e73468f2a', notification.invoice
- assert_equal 'C0Dr8m', notification.account
+ assert_equal 'merchant_id', notification.account
assert_equal '10.00', notification.gross
assert_equal '0.00', notification.discount
assert_equal nil, notification.offer_description
@@ -48,7 +48,7 @@ def test_return_has_notification
assert_equal 'Payu-Admin', notification.customer_first_name
assert_equal '', notification.customer_last_name
assert_equal ["", "", "", "", "", "", "", "", "", ""], notification.user_defined
- assert_equal 'ef0c1b509a42b802a4938c25dc9bb9efe40b75a7dfb8bde1a6f126fa1f86cee264c5e5a17e87db85150d6d8912eafda838416e669712f1989dcb9cbdb8c24219', notification.checksum
+ assert_equal checksum, notification.checksum
assert_equal 'E000', notification.message
assert notification.checksum_ok?
end
@@ -56,11 +56,15 @@ def test_return_has_notification
private
def http_raw_data_success
- "mihpayid=403993715508030204&mode=CC&status=success&unmappedstatus=captured&key=C0Dr8m&txnid=4ba4afe87f7e73468f2a&amount=10.00&discount=0.00&addedon=2013-05-10 18 32 30&productinfo=Product Info&firstname=Payu-Admin&lastname=&address1=&address2=&city=&state=&country=&zipcode=&email=test@example.com&phone=1234567890&udf1=&udf2=&udf3=&udf4=&udf5=&udf6=&udf7=&udf8=&udf9=&udf10=&hash=ef0c1b509a42b802a4938c25dc9bb9efe40b75a7dfb8bde1a6f126fa1f86cee264c5e5a17e87db85150d6d8912eafda838416e669712f1989dcb9cbdb8c24219&field1=313069903923&field2=999999&field3=59117331831301&field4=-1&field5=&field6=&field7=&field8=&PG_TYPE=HDFC&bank_ref_num=59117331831301&bankcode=CC&error=E000&cardnum=512345XXXXXX2346&cardhash=766f0227cc4b4c5f773a04cb31d8d1c5be071dd8d08fe365ecf5e2e5c947546d"
+ "mihpayid=403993715508030204&mode=CC&status=success&unmappedstatus=captured&key=merchant_id&txnid=4ba4afe87f7e73468f2a&amount=10.00&discount=0.00&addedon=2013-05-10 18 32 30&productinfo=Product Info&firstname=Payu-Admin&lastname=&address1=&address2=&city=&state=&country=&zipcode=&email=test@example.com&phone=1234567890&udf1=&udf2=&udf3=&udf4=&udf5=&udf6=&udf7=&udf8=&udf9=&udf10=&hash=#{checksum}&field1=313069903923&field2=999999&field3=59117331831301&field4=-1&field5=&field6=&field7=&field8=&PG_TYPE=HDFC&bank_ref_num=59117331831301&bankcode=CC&error=E000&cardnum=512345XXXXXX2346&cardhash=766f0227cc4b4c5f773a04cb31d8d1c5be071dd8d08fe365ecf5e2e5c947546d"
end
def http_raw_data_failure
- "mihpayid=403993715508030204&mode=CC&status=failure&unmappedstatus=failed&key=C0Dr8m&txnid=8ae1034d1abf47fde1cf&amount=10.00&discount=0.00&addedon=2013-05-13 11:09:20&productinfo=Product Info&firstname=Payu-Admin&lastname=&address1=&address2=&city=&state=&country=&zipcode=&email=test@example.com&phone=1234567890&udf1=&udf2=&udf3=&udf4=&udf5=&udf6=&udf7=&udf8=&udf9=&udf10=&hash=65774f82abe64cec54be31107529b2a3eef8f6a3f97a8cb81e9769f4394b890b0e7171f8988c4df3684e7f9f337035d0fe09a844da4b76e68dd643e8ac5e5c63&field1=&field2=&field3=&field4=&field5=!ERROR!-GV00103-Invalid BrandError Code: GV00103&field6=&field7=&field8=failed in enrollment&PG_TYPE=HDFC&bank_ref_num=&bankcode=CC&error=E201&cardnum=411111XXXXXX1111&cardhash=49c73d6c44f27f7ac71b439de842f91e27fcbc3b9ce9dfbcbf1ce9a8fe790c17"
+ "mihpayid=403993715508030204&mode=CC&status=failure&unmappedstatus=failed&key=merchant_id&txnid=8ae1034d1abf47fde1cf&amount=10.00&discount=0.00&addedon=2013-05-13 11:09:20&productinfo=Product Info&firstname=Payu-Admin&lastname=&address1=&address2=&city=&state=&country=&zipcode=&email=test@example.com&phone=1234567890&udf1=&udf2=&udf3=&udf4=&udf5=&udf6=&udf7=&udf8=&udf9=&udf10=&hash=65774f82abe64cec54be31107529b2a3eef8f6a3f97a8cb81e9769f4394b890b0e7171f8988c4df3684e7f9f337035d0fe09a844da4b76e68dd643e8ac5e5c63&field1=&field2=&field3=&field4=&field5=!ERROR!-GV00103-Invalid BrandError Code: GV00103&field6=&field7=&field8=failed in enrollment&PG_TYPE=HDFC&bank_ref_num=&bankcode=CC&error=E201&cardnum=411111XXXXXX1111&cardhash=49c73d6c44f27f7ac71b439de842f91e27fcbc3b9ce9dfbcbf1ce9a8fe790c17"
+ end
+
+ def checksum
+ Digest::SHA512.hexdigest("secret|success|||||||||||test@example.com|Payu-Admin|Product Info|10.00|4ba4afe87f7e73468f2a|merchant_id")
end
end
diff --git a/test/unit/integrations/returns/wirecard_checkout_page_return_test.rb b/test/unit/integrations/returns/wirecard_checkout_page_return_test.rb
new file mode 100644
index 00000000000..0dc022b0452
--- /dev/null
+++ b/test/unit/integrations/returns/wirecard_checkout_page_return_test.rb
@@ -0,0 +1,20 @@
+require 'test_helper'
+
+class WirecardCheckoutPageReturnTest < Test::Unit::TestCase
+ include ActiveMerchant::Billing::Integrations
+
+ def setup
+ @options = fixtures(:wirecard_checkout_page)
+ @return = WirecardCheckoutPage::Return.new(http_raw_data, @options)
+ end
+
+ def test_return
+ assert @return.success?
+ end
+
+ private
+ def http_raw_data
+ "amount=110.99¤cy=EUR&paymentType=IDL&financialInstitution=INGBANK&language=de&orderNumber=9882408&paymentState=SUCCESS&utf8=%E2%9C%93&xActiveMerchantOrderId=13&consumerIpAddress=192.168.201.181&consumerUserAgent=Mozilla%2F5.0+%28X11%3B+Ubuntu%3B+Linux+x86_64%3B+rv%3A24.0%29+Gecko%2F20100101+Firefox%2F24.0&commit=Jetzt+bezahlen&idealConsumerName=Test+C%C3%B6ns%C3%BCmer+Utl%C3%B8psdato&idealConsumerBIC=RABONL2U&idealConsumerCity=RABONL2U&idealConsumerIBAN=NL17RABO0213698412&idealConsumerAccountNumber=NL17RABO0213698412&gatewayReferenceNumber=DGW_9882408_RN&gatewayContractNumber=DemoContractNumber123&avsResponseCode=X&avsResponseMessage=Demo+AVS+ResultMessage&responseFingerprintOrder=amount%2Ccurrency%2CpaymentType%2CfinancialInstitution%2Clanguage%2CorderNumber%2CpaymentState%2Cutf8%2CxActiveMerchantOrderId%2CconsumerIpAddress%2CconsumerUserAgent%2Ccommit%2CidealConsumerName%2CidealConsumerBIC%2CidealConsumerCity%2CidealConsumerIBAN%2CidealConsumerAccountNumber%2CgatewayReferenceNumber%2CgatewayContractNumber%2CavsResponseCode%2CavsResponseMessage%2Csecret%2CresponseFingerprintOrder&responseFingerprint=a15a4fceefcab5a41380f97079180d55"
+ end
+
+end
diff --git a/test/unit/integrations/wirecard_checkout_page_module_test.rb b/test/unit/integrations/wirecard_checkout_page_module_test.rb
new file mode 100644
index 00000000000..454d9752a9c
--- /dev/null
+++ b/test/unit/integrations/wirecard_checkout_page_module_test.rb
@@ -0,0 +1,9 @@
+require 'test_helper'
+
+class WirecardCheckoutPageModuleTest < Test::Unit::TestCase
+ include ActiveMerchant::Billing::Integrations
+
+ def test_notification_method
+ assert_instance_of WirecardCheckoutPage::Notification, WirecardCheckoutPage.notification('name=cody', {})
+ end
+end