├── .gitignore ├── generators ├── gateway │ ├── USAGE │ ├── templates │ │ ├── gateway_test.rb │ │ ├── remote_gateway_test.rb │ │ └── gateway.rb │ └── gateway_generator.rb └── integration │ ├── USAGE │ ├── templates │ ├── module_test.rb │ ├── integration.rb │ ├── notification_test.rb │ ├── helper.rb │ └── helper_test.rb │ └── integration_generator.rb ├── lib ├── active_merchant │ ├── lib │ │ ├── error.rb │ │ ├── utils.rb │ │ ├── post_data.rb │ │ ├── requires_parameters.rb │ │ └── validateable.rb │ └── billing │ │ ├── gateways.rb │ │ ├── integrations │ │ ├── bogus │ │ │ ├── return.rb │ │ │ ├── notification.rb │ │ │ └── helper.rb │ │ ├── gestpay │ │ │ ├── return.rb │ │ │ ├── common.rb │ │ │ ├── helper.rb │ │ │ └── notification.rb │ │ ├── nochex │ │ │ ├── return.rb │ │ │ └── helper.rb │ │ ├── paypal │ │ │ └── return.rb │ │ ├── chronopay │ │ │ ├── return.rb │ │ │ └── helper.rb │ │ ├── two_checkout │ │ │ ├── return.rb │ │ │ └── helper.rb │ │ ├── bogus.rb │ │ ├── chronopay.rb │ │ ├── two_checkout.rb │ │ ├── gestpay.rb │ │ ├── hi_trust.rb │ │ ├── return.rb │ │ ├── paypal.rb │ │ ├── hi_trust │ │ │ ├── notification.rb │ │ │ └── helper.rb │ │ ├── notification.rb │ │ └── action_view_helper.rb │ │ ├── gateways │ │ ├── paypal_nv │ │ │ ├── paypal_express_reference_nv_response.rb │ │ │ └── paypal_express_nv_response.rb │ │ ├── payflow │ │ │ ├── payflow_response.rb │ │ │ └── payflow_express_response.rb │ │ ├── payflow_express_uk.rb │ │ ├── paypal_ca.rb │ │ ├── paypal_express_common.rb │ │ ├── payflow_uk.rb │ │ ├── payflow_nv │ │ │ ├── payflow_nv_response.rb │ │ │ └── payflow_express_nv_response.rb │ │ ├── secure_pay.rb │ │ ├── paypal │ │ │ └── paypal_express_response.rb │ │ ├── modern_payments.rb │ │ ├── beanstream_interac.rb │ │ ├── paypal_nv.rb │ │ └── sage │ │ │ └── sage_bankcard.rb │ │ ├── credit_card_formatting.rb │ │ ├── expiry_date.rb │ │ ├── integrations.rb │ │ ├── response.rb │ │ ├── cvv_result.rb │ │ ├── base.rb │ │ └── check.rb ├── support │ └── gateway_support.rb ├── tasks │ └── cia.rb └── active_merchant.rb ├── init.rb ├── test ├── unit │ ├── utils_test.rb │ ├── integrations │ │ ├── returns │ │ │ ├── return_test.rb │ │ │ ├── nochex_return_test.rb │ │ │ ├── paypal_return_test.rb │ │ │ ├── gestpay_return_test.rb │ │ │ ├── chronopay_return_test.rb │ │ │ ├── hi_trust_return_test.rb │ │ │ └── two_checkout_return_test.rb │ │ ├── nochex_module_test.rb │ │ ├── hi_trust_module_test.rb │ │ ├── chronopay_module_test.rb │ │ ├── two_checkout_module_test.rb │ │ ├── helpers │ │ │ ├── hi_trust_helper_test.rb │ │ │ ├── bogus_helper_test.rb │ │ │ ├── nochex_helper_test.rb │ │ │ └── chronopay_helper_test.rb │ │ ├── bogus_module_test.rb │ │ ├── gestpay_module_test.rb │ │ ├── paypal_module_test.rb │ │ ├── action_view_helper_test.rb │ │ └── notifications │ │ │ ├── nochex_notification_test.rb │ │ │ ├── hi_trust_notification_test.rb │ │ │ ├── two_checkout_notification_test.rb │ │ │ ├── chronopay_notification_test.rb │ │ │ └── gestpay_notification_test.rb │ ├── gateways │ │ ├── payflow_express_uk_test.rb │ │ ├── payflow_uk_test.rb │ │ ├── bogus_test.rb │ │ ├── secure_pay_tech_test.rb │ │ ├── gateway_test.rb │ │ ├── netbilling_test.rb │ │ ├── pay_secure_test.rb │ │ ├── trust_commerce_test.rb │ │ ├── psl_card_test.rb │ │ ├── secure_pay_test.rb │ │ └── sage_virtual_check_test.rb │ ├── generators │ │ ├── test_generator_helper.rb │ │ ├── test_gateway_generator.rb │ │ └── test_integration_generator.rb │ ├── credit_card_formatting_test.rb │ ├── expiry_date_test.rb │ ├── country_code_test.rb │ ├── cvv_result_test.rb │ ├── response_test.rb │ ├── post_data_test.rb │ ├── validateable_test.rb │ ├── avs_result_test.rb │ ├── base_test.rb │ ├── country_test.rb │ └── check_test.rb ├── remote │ ├── integrations │ │ ├── remote_paypal_integration_test.rb │ │ └── remote_gestpay_integration_test.rb │ └── gateways │ │ ├── remote_secure_pay_test.rb │ │ ├── remote_trans_first_test.rb │ │ ├── remote_secure_pay_au_test.rb │ │ ├── remote_pay_secure_test.rb │ │ ├── remote_secure_pay_tech_test.rb │ │ ├── remote_viaklix_test.rb │ │ ├── remote_modern_payments_test.rb │ │ ├── remote_beanstream_interac_test.rb │ │ ├── remote_usa_epay_test.rb │ │ ├── remote_paypal_express_nv_test.rb │ │ ├── remote_paypal_express_test.rb │ │ ├── remote_psigate_test.rb │ │ ├── remote_sage_virtual_check_test.rb │ │ ├── remote_payflow_express_test.rb │ │ ├── remote_modern_payments_cim_test.rb │ │ ├── remote_payflow_express_nv_test.rb │ │ ├── remote_exact_test.rb │ │ ├── remote_netbilling_test.rb │ │ ├── remote_eway_test.rb │ │ ├── remote_efsnet_test.rb │ │ ├── remote_moneris_test.rb │ │ ├── remote_wirecard_test.rb │ │ ├── remote_sage_test.rb │ │ └── remote_plugnpay_test.rb └── extra │ └── binding_of_caller.rb ├── script ├── destroy └── generate ├── MIT-LICENSE ├── gem-public_cert.pem └── CONTRIBUTERS /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | -------------------------------------------------------------------------------- /generators/gateway/USAGE: -------------------------------------------------------------------------------- 1 | Description: 2 | 3 | 4 | Usage: 5 | 6 | -------------------------------------------------------------------------------- /generators/integration/USAGE: -------------------------------------------------------------------------------- 1 | Description: 2 | 3 | 4 | Usage: 5 | 6 | -------------------------------------------------------------------------------- /lib/active_merchant/lib/error.rb: -------------------------------------------------------------------------------- 1 | module ActiveMerchant #:nodoc: 2 | class ActiveMerchantError < StandardError #:nodoc: 3 | end 4 | end -------------------------------------------------------------------------------- /lib/active_merchant/billing/gateways.rb: -------------------------------------------------------------------------------- 1 | require 'active_merchant/billing/gateway' 2 | 3 | Dir[File.dirname(__FILE__) + '/gateways/*.rb'].each{|g| require g} -------------------------------------------------------------------------------- /init.rb: -------------------------------------------------------------------------------- 1 | require 'active_merchant' 2 | require 'active_merchant/billing/integrations/action_view_helper' 3 | ActionView::Base.send(:include, ActiveMerchant::Billing::Integrations::ActionViewHelper) 4 | -------------------------------------------------------------------------------- /test/unit/utils_test.rb: -------------------------------------------------------------------------------- 1 | require File.dirname(__FILE__) + '/../test_helper' 2 | 3 | class UtilsTest < Test::Unit::TestCase 4 | def test_unique_id_should_be_32_chars_and_alphanumeric 5 | assert_match /^\w{32}$/, ActiveMerchant::Utils.generate_unique_id 6 | end 7 | end -------------------------------------------------------------------------------- /test/unit/integrations/returns/return_test.rb: -------------------------------------------------------------------------------- 1 | require File.dirname(__FILE__) + '/../../../test_helper' 2 | 3 | class ReturnTest < Test::Unit::TestCase 4 | include ActiveMerchant::Billing::Integrations 5 | 6 | 7 | def test_return 8 | r = Return.new('') 9 | assert r.success? 10 | end 11 | end -------------------------------------------------------------------------------- /lib/active_merchant/billing/integrations/bogus/return.rb: -------------------------------------------------------------------------------- 1 | module ActiveMerchant #:nodoc: 2 | module Billing #:nodoc: 3 | module Integrations #:nodoc: 4 | module Bogus 5 | class Return < ActiveMerchant::Billing::Integrations::Return 6 | end 7 | end 8 | end 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /lib/active_merchant/billing/integrations/gestpay/return.rb: -------------------------------------------------------------------------------- 1 | module ActiveMerchant #:nodoc: 2 | module Billing #:nodoc: 3 | module Integrations #:nodoc: 4 | module Gestpay 5 | class Return < ActiveMerchant::Billing::Integrations::Return 6 | end 7 | end 8 | end 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /lib/active_merchant/billing/integrations/nochex/return.rb: -------------------------------------------------------------------------------- 1 | module ActiveMerchant #:nodoc: 2 | module Billing #:nodoc: 3 | module Integrations #:nodoc: 4 | module Nochex 5 | class Return < ActiveMerchant::Billing::Integrations::Return 6 | end 7 | end 8 | end 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /lib/active_merchant/billing/integrations/paypal/return.rb: -------------------------------------------------------------------------------- 1 | module ActiveMerchant #:nodoc: 2 | module Billing #:nodoc: 3 | module Integrations #:nodoc: 4 | module Paypal 5 | class Return < ActiveMerchant::Billing::Integrations::Return 6 | end 7 | end 8 | end 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /lib/active_merchant/billing/integrations/chronopay/return.rb: -------------------------------------------------------------------------------- 1 | module ActiveMerchant #:nodoc: 2 | module Billing #:nodoc: 3 | module Integrations #:nodoc: 4 | module Chronopay 5 | class Return < ActiveMerchant::Billing::Integrations::Return 6 | end 7 | end 8 | end 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /test/unit/integrations/returns/nochex_return_test.rb: -------------------------------------------------------------------------------- 1 | require File.dirname(__FILE__) + '/../../../test_helper' 2 | 3 | class NochexReturnTest < Test::Unit::TestCase 4 | include ActiveMerchant::Billing::Integrations 5 | 6 | def test_return 7 | r = Nochex::Return.new('') 8 | assert r.success? 9 | end 10 | end -------------------------------------------------------------------------------- /test/unit/integrations/returns/paypal_return_test.rb: -------------------------------------------------------------------------------- 1 | require File.dirname(__FILE__) + '/../../../test_helper' 2 | 3 | class PaypalReturnTest < Test::Unit::TestCase 4 | include ActiveMerchant::Billing::Integrations 5 | 6 | def test_return 7 | r = Paypal::Return.new('') 8 | assert r.success? 9 | end 10 | end -------------------------------------------------------------------------------- /test/unit/integrations/returns/gestpay_return_test.rb: -------------------------------------------------------------------------------- 1 | require File.dirname(__FILE__) + '/../../../test_helper' 2 | 3 | class GestpayReturnTest < Test::Unit::TestCase 4 | include ActiveMerchant::Billing::Integrations 5 | 6 | def test_return 7 | r = Gestpay::Return.new('') 8 | assert r.success? 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /lib/active_merchant/billing/gateways/paypal_nv/paypal_express_reference_nv_response.rb: -------------------------------------------------------------------------------- 1 | module ActiveMerchant #:nodoc: 2 | module Billing #:nodoc: 3 | class PaypalExpressReferenceNvResponse < PaypalExpressNvResponse 4 | def token 5 | @params['billingagreementid'] || @params['token'] 6 | end 7 | end 8 | end 9 | end -------------------------------------------------------------------------------- /lib/active_merchant/billing/integrations/bogus/notification.rb: -------------------------------------------------------------------------------- 1 | module ActiveMerchant #:nodoc: 2 | module Billing #:nodoc: 3 | module Integrations #:nodoc: 4 | module Bogus 5 | class Notification < ActiveMerchant::Billing::Integrations::Notification 6 | 7 | end 8 | end 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /test/unit/integrations/returns/chronopay_return_test.rb: -------------------------------------------------------------------------------- 1 | require File.dirname(__FILE__) + '/../../../test_helper' 2 | 3 | class ChronopayReturnTest < Test::Unit::TestCase 4 | include ActiveMerchant::Billing::Integrations 5 | 6 | def test_return 7 | r = Chronopay::Return.new('') 8 | assert r.success? 9 | end 10 | end 11 | 12 | -------------------------------------------------------------------------------- /generators/integration/templates/module_test.rb: -------------------------------------------------------------------------------- 1 | require File.dirname(__FILE__) + '/../../test_helper' 2 | 3 | class <%= class_name %>ModuleTest < Test::Unit::TestCase 4 | include ActiveMerchant::Billing::Integrations 5 | 6 | def test_notification_method 7 | assert_instance_of <%= class_name %>::Notification, <%= class_name %>.notification('name=cody') 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /script/destroy: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | APP_ROOT = File.join(File.dirname(__FILE__), '..') 3 | 4 | begin 5 | require 'rubigen' 6 | rescue LoadError 7 | require 'rubygems' 8 | require 'rubigen' 9 | end 10 | require 'rubigen/scripts/destroy' 11 | 12 | ARGV.shift if ['--help', '-h'].include?(ARGV[0]) 13 | RubiGen::Base.use_component_sources! [:activemerchant, :rubygems, :test_unit] 14 | RubiGen::Scripts::Destroy.new.run(ARGV) 15 | -------------------------------------------------------------------------------- /lib/active_merchant/billing/gateways/payflow/payflow_response.rb: -------------------------------------------------------------------------------- 1 | module ActiveMerchant #:nodoc: 2 | module Billing #:nodoc: 3 | class PayflowResponse < Response 4 | def profile_id 5 | @params['profile_id'] 6 | end 7 | 8 | def payment_history 9 | @payment_history ||= @params['rp_payment_result'].collect{ |result| result.stringify_keys } rescue [] 10 | end 11 | end 12 | end 13 | end -------------------------------------------------------------------------------- /script/generate: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | APP_ROOT = File.join(File.dirname(__FILE__), '..') 3 | 4 | begin 5 | require 'rubigen' 6 | rescue LoadError 7 | require 'rubygems' 8 | require 'rubigen' 9 | end 10 | require 'rubigen/scripts/generate' 11 | 12 | ARGV.shift if ['--help', '-h'].include?(ARGV[0]) 13 | RubiGen::Base.use_component_sources! [:activemerchant, :rubygems, :test_unit] 14 | RubiGen::Scripts::Generate.new.run(ARGV) 15 | -------------------------------------------------------------------------------- /test/unit/gateways/payflow_express_uk_test.rb: -------------------------------------------------------------------------------- 1 | require File.dirname(__FILE__) + '/../../test_helper' 2 | 3 | class PayflowExpressUkTest < Test::Unit::TestCase 4 | def setup 5 | @gateway = PayflowExpressUkGateway.new( 6 | :login => 'LOGIN', 7 | :password => 'PASSWORD' 8 | ) 9 | end 10 | 11 | def test_supported_countries 12 | assert_equal ['GB'], PayflowExpressUkGateway.supported_countries 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /lib/active_merchant/lib/utils.rb: -------------------------------------------------------------------------------- 1 | require 'digest/md5' 2 | 3 | module ActiveMerchant #:nodoc: 4 | module Utils #:nodoc: 5 | def generate_unique_id 6 | md5 = Digest::MD5.new 7 | now = Time.now 8 | md5 << now.to_s 9 | md5 << String(now.usec) 10 | md5 << String(rand(0)) 11 | md5 << String($$) 12 | md5 << self.class.name 13 | md5.hexdigest 14 | end 15 | 16 | module_function :generate_unique_id 17 | end 18 | end -------------------------------------------------------------------------------- /test/unit/integrations/nochex_module_test.rb: -------------------------------------------------------------------------------- 1 | require File.dirname(__FILE__) + '/../../test_helper' 2 | 3 | class ChronopayModuleTest < Test::Unit::TestCase 4 | include ActiveMerchant::Billing::Integrations 5 | 6 | def test_notification_method 7 | assert_instance_of Nochex::Notification, Nochex.notification('name=cody') 8 | end 9 | 10 | def test_return_method 11 | assert_instance_of Nochex::Return, Nochex.return('name=cody') 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /test/unit/integrations/hi_trust_module_test.rb: -------------------------------------------------------------------------------- 1 | require File.dirname(__FILE__) + '/../../test_helper' 2 | 3 | class HiTrustModuleTest < Test::Unit::TestCase 4 | include ActiveMerchant::Billing::Integrations 5 | 6 | def test_notification_method 7 | assert_instance_of HiTrust::Notification, HiTrust.notification('name=cody') 8 | end 9 | 10 | def test_return_method 11 | assert_instance_of HiTrust::Return, HiTrust.return('name=cody') 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /test/unit/integrations/chronopay_module_test.rb: -------------------------------------------------------------------------------- 1 | require File.dirname(__FILE__) + '/../../test_helper' 2 | 3 | class ChronopayModuleTest < Test::Unit::TestCase 4 | include ActiveMerchant::Billing::Integrations 5 | 6 | def test_notification_method 7 | assert_instance_of Chronopay::Notification, Chronopay.notification('name=cody') 8 | end 9 | 10 | def test_return_method 11 | assert_instance_of Chronopay::Return, Chronopay.return('name=cody') 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /test/unit/integrations/two_checkout_module_test.rb: -------------------------------------------------------------------------------- 1 | require File.dirname(__FILE__) + '/../../test_helper' 2 | 3 | class TwoCheckoutModuleTest < Test::Unit::TestCase 4 | include ActiveMerchant::Billing::Integrations 5 | 6 | def test_notification_method 7 | assert_instance_of TwoCheckout::Notification, TwoCheckout.notification('name=cody') 8 | end 9 | 10 | def test_return_method 11 | assert_instance_of TwoCheckout::Return, TwoCheckout.return('name=cody') 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /lib/active_merchant/billing/integrations/two_checkout/return.rb: -------------------------------------------------------------------------------- 1 | module ActiveMerchant #:nodoc: 2 | module Billing #:nodoc: 3 | module Integrations #:nodoc: 4 | module TwoCheckout 5 | class Return < ActiveMerchant::Billing::Integrations::Return 6 | def success? 7 | params['credit_card_processed'] == 'Y' 8 | end 9 | 10 | def message 11 | 12 | end 13 | end 14 | end 15 | end 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /generators/integration/templates/integration.rb: -------------------------------------------------------------------------------- 1 | require File.dirname(__FILE__) + '/<%= name %>/helper.rb' 2 | require File.dirname(__FILE__) + '/<%= name %>/notification.rb' 3 | 4 | module ActiveMerchant #:nodoc: 5 | module Billing #:nodoc: 6 | module Integrations #:nodoc: 7 | module <%= class_name %> 8 | 9 | mattr_accessor :service_url 10 | self.service_url = 'https://www.example.com' 11 | 12 | def self.notification(post) 13 | Notification.new(post) 14 | end 15 | end 16 | end 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /lib/active_merchant/lib/post_data.rb: -------------------------------------------------------------------------------- 1 | require 'cgi' 2 | 3 | class PostData < Hash 4 | class_inheritable_accessor :required_fields, :instance_writer => false 5 | self.required_fields = [] 6 | 7 | def []=(key, value) 8 | return if value.blank? && !required?(key) 9 | super 10 | end 11 | 12 | def to_post_data 13 | collect { |key, value| "#{key}=#{CGI.escape(value.to_s)}" }.join("&") 14 | end 15 | 16 | alias_method :to_s, :to_post_data 17 | 18 | private 19 | def required?(key) 20 | required_fields.include?(key) 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /lib/active_merchant/billing/gateways/payflow_express_uk.rb: -------------------------------------------------------------------------------- 1 | require File.dirname(__FILE__) + '/payflow_express' 2 | 3 | module ActiveMerchant #:nodoc: 4 | module Billing #:nodoc: 5 | class PayflowExpressUkGateway < PayflowExpressGateway 6 | self.default_currency = 'GBP' 7 | self.partner = 'PayPalUk' 8 | 9 | self.supported_countries = ['GB'] 10 | self.homepage_url = 'https://www.paypal.com/uk/cgi-bin/webscr?cmd=_additional-payment-overview-outside' 11 | self.display_name = 'PayPal Express Checkout (UK)' 12 | end 13 | end 14 | end 15 | 16 | -------------------------------------------------------------------------------- /test/unit/integrations/helpers/hi_trust_helper_test.rb: -------------------------------------------------------------------------------- 1 | require File.dirname(__FILE__) + '/../../../test_helper' 2 | 3 | class HiTrustHelperTest < Test::Unit::TestCase 4 | include ActiveMerchant::Billing::Integrations 5 | 6 | def setup 7 | @helper = HiTrust::Helper.new('order-500','cody@example.com', :amount => 500, :currency => 'USD') 8 | end 9 | 10 | def test_basic_helper_fields 11 | assert_field 'storeid', 'cody@example.com' 12 | assert_field 'amount', '500' 13 | assert_field 'ordernumber', 'order-500' 14 | assert_field 'currency', 'USD' 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /lib/active_merchant/billing/gateways/paypal_ca.rb: -------------------------------------------------------------------------------- 1 | require File.dirname(__FILE__) + '/paypal' 2 | 3 | module ActiveMerchant #:nodoc: 4 | module Billing #:nodoc: 5 | # The PayPal gateway for PayPal Website Payments Pro Canada only supports Visa and MasterCard 6 | class PaypalCaGateway < PaypalGateway 7 | self.supported_cardtypes = [:visa, :master] 8 | self.supported_countries = ['CA'] 9 | self.homepage_url = 'https://www.paypal.com/cgi-bin/webscr?cmd=_wp-pro-overview-outside' 10 | self.display_name = 'PayPal Website Payments Pro (CA)' 11 | end 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /lib/active_merchant/billing/integrations/bogus/helper.rb: -------------------------------------------------------------------------------- 1 | module ActiveMerchant #:nodoc: 2 | module Billing #:nodoc: 3 | module Integrations #:nodoc: 4 | module Bogus 5 | class Helper < ActiveMerchant::Billing::Integrations::Helper 6 | mapping :account, 'account' 7 | mapping :order, 'order' 8 | mapping :amount, 'amount' 9 | mapping :currency, 'currency' 10 | mapping :customer, :first_name => 'first_name', 11 | :last_name => 'last_name' 12 | 13 | end 14 | end 15 | end 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /test/unit/generators/test_generator_helper.rb: -------------------------------------------------------------------------------- 1 | require File.dirname(__FILE__) + '/../../test_helper' 2 | require 'fileutils' 3 | 4 | # Must set before requiring generator libs. 5 | TMP_ROOT = File.dirname(__FILE__) + "/tmp" unless defined?(TMP_ROOT) 6 | PROJECT_NAME = "myproject" unless defined?(PROJECT_NAME) 7 | app_root = File.join(TMP_ROOT, PROJECT_NAME) 8 | if defined?(APP_ROOT) 9 | APP_ROOT.replace(app_root) 10 | else 11 | APP_ROOT = app_root 12 | end 13 | 14 | begin 15 | require 'rubigen' 16 | rescue LoadError 17 | require 'rubygems' 18 | require 'rubigen' 19 | end 20 | require 'rubigen/helpers/generator_test_helper' 21 | -------------------------------------------------------------------------------- /test/unit/integrations/bogus_module_test.rb: -------------------------------------------------------------------------------- 1 | require File.dirname(__FILE__) + '/../../test_helper' 2 | 3 | class BogusModuleTest < Test::Unit::TestCase 4 | include ActiveMerchant::Billing::Integrations 5 | 6 | def test_notification_method 7 | assert_instance_of Bogus::Notification, Bogus.notification('name=cody') 8 | end 9 | 10 | def test_service_url 11 | new = 'http://www.unbogus.com' 12 | assert_equal 'http://www.bogus.com', Bogus.service_url 13 | Bogus.service_url = new 14 | assert_equal new, Bogus.service_url 15 | end 16 | 17 | def test_return_method 18 | assert_instance_of Bogus::Return, Bogus.return('name=cody') 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /lib/active_merchant/billing/credit_card_formatting.rb: -------------------------------------------------------------------------------- 1 | module ActiveMerchant #:nodoc: 2 | module Billing #:nodoc: 3 | module CreditCardFormatting 4 | 5 | # This method is used to format numerical information pertaining to credit cards. 6 | # 7 | # format(2005, :two_digits) # => "05" 8 | # format(05, :four_digits) # => "0005" 9 | def format(number, option) 10 | return '' if number.blank? 11 | 12 | case option 13 | when :two_digits ; sprintf("%.2i", number)[-2..-1] 14 | when :four_digits ; sprintf("%.4i", number)[-4..-1] 15 | else number 16 | end 17 | end 18 | 19 | end 20 | end 21 | end -------------------------------------------------------------------------------- /test/unit/credit_card_formatting_test.rb: -------------------------------------------------------------------------------- 1 | require File.dirname(__FILE__) + '/../test_helper' 2 | 3 | class CreditCardFormattingTest < Test::Unit::TestCase 4 | include ActiveMerchant::Billing::CreditCardFormatting 5 | 6 | def test_should_format_number_by_rule 7 | assert_equal 2005, format(2005, :steven_colbert) 8 | 9 | assert_equal '0005', format(05, :four_digits) 10 | assert_equal '2005', format(2005, :four_digits) 11 | 12 | assert_equal '05', format(2005, :two_digits) 13 | assert_equal '05', format(05, :two_digits) 14 | assert_equal '08', format(8, :two_digits) 15 | 16 | assert format(nil, :two_digits).blank? 17 | assert format('', :two_digits).blank? 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /lib/active_merchant/billing/integrations/bogus.rb: -------------------------------------------------------------------------------- 1 | require 'active_merchant/billing/integrations/bogus/helper.rb' 2 | require 'active_merchant/billing/integrations/bogus/notification.rb' 3 | require 'active_merchant/billing/integrations/bogus/return.rb' 4 | 5 | module ActiveMerchant #:nodoc: 6 | module Billing #:nodoc: 7 | module Integrations #:nodoc: 8 | module Bogus 9 | mattr_accessor :service_url 10 | self.service_url = 'http://www.bogus.com' 11 | 12 | def self.notification(post) 13 | Notification.new(post) 14 | end 15 | 16 | def self.return(query_string) 17 | Return.new(query_string) 18 | end 19 | end 20 | end 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /test/unit/expiry_date_test.rb: -------------------------------------------------------------------------------- 1 | require File.dirname(__FILE__) + '/../test_helper' 2 | 3 | class ExpiryDateTest < Test::Unit::TestCase 4 | def test_should_be_expired 5 | last_month = 2.months.ago 6 | date = CreditCard::ExpiryDate.new(last_month.month, last_month.year) 7 | assert date.expired? 8 | end 9 | 10 | def test_today_should_not_be_expired 11 | today = Time.now 12 | date = CreditCard::ExpiryDate.new(today.month, today.year) 13 | assert_false date.expired? 14 | end 15 | 16 | def test_dates_in_the_future_should_not_be_expired 17 | next_month = 1.month.from_now 18 | date = CreditCard::ExpiryDate.new(next_month.month, next_month.year) 19 | assert_false date.expired? 20 | end 21 | end -------------------------------------------------------------------------------- /lib/active_merchant/lib/requires_parameters.rb: -------------------------------------------------------------------------------- 1 | module ActiveMerchant #:nodoc: 2 | module RequiresParameters #:nodoc: 3 | def requires!(hash, *params) 4 | params.each do |param| 5 | if param.is_a?(Array) 6 | raise ArgumentError.new("Missing required parameter: #{param.first}") unless hash.has_key?(param.first) 7 | 8 | valid_options = param[1..-1] 9 | raise ArgumentError.new("Parameter: #{param.first} must be one of #{valid_options.to_sentence(:connector => 'or')}") unless valid_options.include?(hash[param.first]) 10 | else 11 | raise ArgumentError.new("Missing required parameter: #{param}") unless hash.has_key?(param) 12 | end 13 | end 14 | end 15 | end 16 | end -------------------------------------------------------------------------------- /lib/active_merchant/billing/gateways/paypal_express_common.rb: -------------------------------------------------------------------------------- 1 | module ActiveMerchant 2 | module Billing 3 | module PaypalExpressCommon 4 | def self.included(base) 5 | base.cattr_accessor :test_redirect_url 6 | base.cattr_accessor :live_redirect_url 7 | base.live_redirect_url = 'https://www.paypal.com/cgibin/webscr?cmd=_express-checkout&token=' 8 | end 9 | 10 | def redirect_url 11 | test? ? test_redirect_url : live_redirect_url 12 | end 13 | 14 | def redirect_url_for(token, options = {}) 15 | options = {:review => true}.update(options) 16 | options[:review] ? "#{redirect_url}#{token}" : "#{redirect_url}#{token}&useraction=commit" 17 | end 18 | end 19 | end 20 | end -------------------------------------------------------------------------------- /lib/active_merchant/billing/integrations/chronopay.rb: -------------------------------------------------------------------------------- 1 | require 'active_merchant/billing/integrations/chronopay/helper.rb' 2 | require 'active_merchant/billing/integrations/chronopay/notification.rb' 3 | require 'active_merchant/billing/integrations/chronopay/return.rb' 4 | 5 | module ActiveMerchant #:nodoc: 6 | module Billing #:nodoc: 7 | module Integrations #:nodoc: 8 | module Chronopay 9 | mattr_accessor :service_url 10 | self.service_url = 'https://secure.chronopay.com/index_shop.cgi' 11 | 12 | def self.notification(post) 13 | Notification.new(post) 14 | end 15 | 16 | def self.return(query_string) 17 | Return.new(query_string) 18 | end 19 | end 20 | end 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /lib/active_merchant/billing/integrations/two_checkout.rb: -------------------------------------------------------------------------------- 1 | require File.dirname(__FILE__) + '/two_checkout/helper.rb' 2 | require File.dirname(__FILE__) + '/two_checkout/notification.rb' 3 | require File.dirname(__FILE__) + '/two_checkout/return.rb' 4 | 5 | module ActiveMerchant #:nodoc: 6 | module Billing #:nodoc: 7 | module Integrations #:nodoc: 8 | module TwoCheckout 9 | 10 | mattr_accessor :service_url 11 | self.service_url = 'https://www.2checkout.com/2co/buyer/purchase' 12 | 13 | def self.notification(post) 14 | Notification.new(post) 15 | end 16 | 17 | def self.return(query_string) 18 | Return.new(query_string) 19 | end 20 | end 21 | end 22 | end 23 | end 24 | -------------------------------------------------------------------------------- /lib/active_merchant/billing/gateways/payflow_uk.rb: -------------------------------------------------------------------------------- 1 | require File.dirname(__FILE__) + '/payflow' 2 | require File.dirname(__FILE__) + '/payflow_express_uk' 3 | 4 | module ActiveMerchant #:nodoc: 5 | module Billing #:nodoc: 6 | class PayflowUkGateway < PayflowGateway 7 | self.default_currency = 'GBP' 8 | self.partner = 'PayPalUk' 9 | 10 | def express 11 | @express ||= PayflowExpressUkGateway.new(@options) 12 | end 13 | 14 | self.supported_cardtypes = [:visa, :master, :american_express, :discover, :solo, :switch] 15 | self.supported_countries = ['GB'] 16 | self.homepage_url = 'https://www.paypal.com/uk/cgi-bin/webscr?cmd=_wp-pro-overview-outside' 17 | self.display_name = 'PayPal Website Payments Pro (UK)' 18 | end 19 | end 20 | end 21 | 22 | -------------------------------------------------------------------------------- /lib/active_merchant/billing/expiry_date.rb: -------------------------------------------------------------------------------- 1 | module ActiveMerchant 2 | module Billing 3 | class CreditCard 4 | class ExpiryDate #:nodoc: 5 | attr_reader :month, :year 6 | def initialize(month, year) 7 | @month = month 8 | @year = year 9 | end 10 | 11 | def expired? #:nodoc: 12 | Time.now > expiration rescue true 13 | end 14 | 15 | def expiration #:nodoc: 16 | Time.parse("#{month}/#{month_days}/#{year} 23:59:59") rescue Time.at(0) 17 | end 18 | 19 | private 20 | def month_days 21 | mdays = [nil,31,28,31,30,31,30,31,31,30,31,30,31] 22 | mdays[2] = 29 if Date.leap?(year) 23 | mdays[month] 24 | end 25 | end 26 | end 27 | end 28 | end -------------------------------------------------------------------------------- /test/remote/integrations/remote_paypal_integration_test.rb: -------------------------------------------------------------------------------- 1 | require File.dirname(__FILE__) + '/../../test_helper' 2 | 3 | class RemotePaypalIntegrationTest < Test::Unit::TestCase 4 | include ActiveMerchant::Billing::Integrations 5 | 6 | def setup 7 | @paypal = Paypal::Notification.new('') 8 | end 9 | 10 | def tear_down 11 | ActiveMerchant::Billing::Base.integration_mode = :test 12 | end 13 | 14 | def test_raw 15 | assert_equal "https://www.sandbox.paypal.com/cgi-bin/webscr", Paypal.service_url 16 | assert_nothing_raised do 17 | assert_equal false, @paypal.acknowledge 18 | end 19 | end 20 | 21 | def test_valid_sender_always_true 22 | ActiveMerchant::Billing::Base.integration_mode = :production 23 | assert @paypal.valid_sender?(nil) 24 | assert @paypal.valid_sender?('127.0.0.1') 25 | end 26 | end 27 | -------------------------------------------------------------------------------- /test/remote/gateways/remote_secure_pay_test.rb: -------------------------------------------------------------------------------- 1 | require File.dirname(__FILE__) + '/../../test_helper' 2 | 3 | class RemoteSecurePayTest < Test::Unit::TestCase 4 | 5 | def setup 6 | @gateway = SecurePayGateway.new(fixtures(:secure_pay)) 7 | 8 | @credit_card = credit_card('4111111111111111', 9 | :month => '7', 10 | :year => '2007' 11 | ) 12 | 13 | @options = { :order_id => generate_unique_id, 14 | :description => 'Store purchase', 15 | :billing_address => address 16 | } 17 | 18 | @amount = 100 19 | end 20 | 21 | def test_successful_purchase 22 | assert response = @gateway.purchase(@amount, @credit_card, @options) 23 | assert response.success? 24 | assert response.test? 25 | assert_equal 'This transaction has been approved', response.message 26 | assert response.authorization 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /test/unit/integrations/gestpay_module_test.rb: -------------------------------------------------------------------------------- 1 | require File.dirname(__FILE__) + '/../../test_helper' 2 | 3 | class GestpayModuleTest < Test::Unit::TestCase 4 | include ActiveMerchant::Billing::Integrations 5 | 6 | def test_notification_method 7 | Gestpay::Notification.any_instance.expects(:ssl_get).returns('#decryptstring#a=9000000&b=PAY1_UICCODE=242*P1*PAY1_AMOUNT=1234.56*P1*PAY1_TRANSACTIONRESULT=OK*P1*PAY1_BANKTRANSACTIONID=ABCD1234*P1*PAY1_SHOPTRANSACTIONID=1000#/decryptstring#') 8 | assert_instance_of Gestpay::Notification, Gestpay.notification('a=900000&b=F7DEB36478FD84760F9134F23C922697272D57DE6D4518EB9B4D468B769D9A3A8071B6EB160B35CB412FC1820C7CC12D17B3141855B1ED55468613702A2E213DDE9DE5B0209E13C416448AE833525959F05693172D7F0656') 9 | end 10 | 11 | def test_return_method 12 | assert_instance_of Gestpay::Return, Gestpay.return('name=cody') 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /test/unit/integrations/returns/hi_trust_return_test.rb: -------------------------------------------------------------------------------- 1 | require File.dirname(__FILE__) + '/../../../test_helper' 2 | 3 | class HiTrustReturnTest < Test::Unit::TestCase 4 | include ActiveMerchant::Billing::Integrations 5 | 6 | def test_successful_return 7 | r = HiTrust::Return.new('order_id=&mscssid=&retcode=00&ordernumber=1138742&type=Auth') 8 | assert r.success? 9 | assert_equal HiTrust::Return::SUCCESS, r.params['retcode'] 10 | assert_equal HiTrust::Return::CODES[HiTrust::Return::SUCCESS], r.message 11 | end 12 | 13 | def test_failed_return 14 | r = HiTrust::Return.new('retcode=-100') 15 | assert_false r.success? 16 | assert_equal HiTrust::Return::CODES['-100'], r.message 17 | end 18 | 19 | def test_unknown_return 20 | r = HiTrust::Return.new('retcode=unknown') 21 | assert_false r.success? 22 | assert_nil r.message 23 | end 24 | end 25 | -------------------------------------------------------------------------------- /lib/active_merchant/billing/integrations/gestpay.rb: -------------------------------------------------------------------------------- 1 | # With help from Giovanni Intini and his code for RGestPay - http://medlar.it/it/progetti/rgestpay 2 | 3 | require File.dirname(__FILE__) + '/gestpay/common.rb' 4 | require File.dirname(__FILE__) + '/gestpay/helper.rb' 5 | require File.dirname(__FILE__) + '/gestpay/notification.rb' 6 | require File.dirname(__FILE__) + '/gestpay/return.rb' 7 | 8 | module ActiveMerchant #:nodoc: 9 | module Billing #:nodoc: 10 | module Integrations #:nodoc: 11 | module Gestpay 12 | 13 | mattr_accessor :service_url 14 | self.service_url = 'https://ecomm.sella.it/gestpay/pagam.asp' 15 | 16 | def self.notification(post) 17 | Notification.new(post) 18 | end 19 | 20 | def self.return(query_string) 21 | Return.new(query_string) 22 | end 23 | end 24 | end 25 | end 26 | end 27 | -------------------------------------------------------------------------------- /test/unit/gateways/payflow_uk_test.rb: -------------------------------------------------------------------------------- 1 | require File.dirname(__FILE__) + '/../../test_helper' 2 | 3 | class PayflowUkTest < Test::Unit::TestCase 4 | def setup 5 | @gateway = PayflowUkGateway.new( 6 | :login => 'LOGIN', 7 | :password => 'PASSWORD' 8 | ) 9 | end 10 | 11 | def test_default_currency 12 | assert_equal 'GBP', PayflowUkGateway.default_currency 13 | end 14 | 15 | def test_express_instance 16 | assert_instance_of PayflowExpressUkGateway, @gateway.express 17 | end 18 | 19 | def test_default_partner 20 | assert_equal 'PayPalUk', PayflowUkGateway.partner 21 | end 22 | 23 | def test_supported_countries 24 | assert_equal ['GB'], PayflowUkGateway.supported_countries 25 | end 26 | 27 | def test_supported_card_types 28 | assert_equal [:visa, :master, :american_express, :discover, :solo, :switch], PayflowUkGateway.supported_cardtypes 29 | end 30 | end 31 | -------------------------------------------------------------------------------- /lib/active_merchant/billing/integrations/hi_trust.rb: -------------------------------------------------------------------------------- 1 | require File.dirname(__FILE__) + '/hi_trust/helper.rb' 2 | require File.dirname(__FILE__) + '/hi_trust/notification.rb' 3 | require File.dirname(__FILE__) + '/hi_trust/return.rb' 4 | 5 | module ActiveMerchant #:nodoc: 6 | module Billing #:nodoc: 7 | module Integrations #:nodoc: 8 | module HiTrust 9 | TEST_URL = 'https://testtrustlink.hitrust.com.tw/TrustLink/TrxReq' 10 | LIVE_URL = 'https://trustlink.hitrust.com.tw/TrustLink/TrxReq' 11 | 12 | def self.service_url 13 | ActiveMerchant::Billing::Base.integration_mode == :test ? TEST_URL : LIVE_URL 14 | end 15 | 16 | def self.notification(post) 17 | Notification.new(post) 18 | end 19 | 20 | def self.return(query_string) 21 | Return.new(query_string) 22 | end 23 | end 24 | end 25 | end 26 | end 27 | -------------------------------------------------------------------------------- /lib/active_merchant/billing/gateways/payflow_nv/payflow_nv_response.rb: -------------------------------------------------------------------------------- 1 | module ActiveMerchant #:nodoc: 2 | module Billing #:nodoc: 3 | class PayflowNvResponse < Response 4 | def profile_id 5 | @params['profileid'] 6 | end 7 | 8 | def payment_history 9 | @payment_history ||= get_history 10 | end 11 | protected 12 | def get_history 13 | hist = [] 14 | @params.reject {|key,val| key !~ /p_result/}.collect {|r| r[0].gsub(/p_result/, "")}.sort.each do |idx| 15 | item = { 16 | 'payment_num' => "#{idx}", 17 | 'amt' => @params["p_amt#{idx}"], 18 | 'transtime' => @params["p_transtime#{idx}"], 19 | 'result' => @params["p_result#{idx}"], 20 | 'state' => @params["p_transtate#{idx}"], 21 | } 22 | hist << item 23 | end 24 | return hist 25 | end 26 | end 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /test/unit/integrations/helpers/bogus_helper_test.rb: -------------------------------------------------------------------------------- 1 | require File.dirname(__FILE__) + '/../../../test_helper' 2 | 3 | class BogusHelperTest < Test::Unit::TestCase 4 | include ActiveMerchant::Billing::Integrations 5 | 6 | def setup 7 | @helper = Bogus::Helper.new('order-500','cfauser', :amount => 500, :currency => 'CAD') 8 | end 9 | 10 | def test_basic_helper_fields 11 | assert_field 'order', 'order-500' 12 | assert_field 'account', 'cfauser' 13 | assert_field 'amount', '500' 14 | assert_field 'currency', 'CAD' 15 | end 16 | 17 | def test_customer_fields 18 | @helper.customer :first_name => 'Cody', :last_name => 'Fauser' 19 | assert_field 'first_name', 'Cody' 20 | assert_field 'last_name', 'Fauser' 21 | end 22 | 23 | def test_setting_unknown_field 24 | fields = @helper.fields.dup 25 | @helper.space_shuttle :name => 'Rockety' 26 | assert_equal fields, @helper.fields 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /lib/active_merchant/billing/integrations.rb: -------------------------------------------------------------------------------- 1 | require 'active_merchant/billing/integrations/notification' 2 | require 'active_merchant/billing/integrations/helper' 3 | require 'active_merchant/billing/integrations/return' 4 | require 'active_merchant/billing/integrations/bogus' 5 | require 'active_merchant/billing/integrations/chronopay' 6 | require 'active_merchant/billing/integrations/paypal' 7 | require 'active_merchant/billing/integrations/nochex' 8 | require 'active_merchant/billing/integrations/gestpay' 9 | require 'active_merchant/billing/integrations/two_checkout' 10 | require 'active_merchant/billing/integrations/hi_trust' 11 | 12 | # make the bogus gateway be classified correctly by the inflector 13 | if defined?(ActiveSupport::Inflector) 14 | ActiveSupport::Inflector.inflections do |inflect| 15 | inflect.uncountable 'bogus' 16 | end 17 | else 18 | Inflector.inflections do |inflect| 19 | inflect.uncountable 'bogus' 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /lib/active_merchant/billing/gateways/secure_pay.rb: -------------------------------------------------------------------------------- 1 | require File.dirname(__FILE__) + '/authorize_net' 2 | 3 | module ActiveMerchant #:nodoc: 4 | module Billing #:nodoc: 5 | class SecurePayGateway < AuthorizeNetGateway 6 | self.live_url = self.test_url = 'https://www.securepay.com/AuthSpayAdapter/process.aspx' 7 | 8 | self.homepage_url = 'http://www.securepay.com/' 9 | self.display_name = 'SecurePay' 10 | 11 | # Limit support to purchase() for the time being 12 | # JRuby chokes here 13 | # undef_method :authorize, :capture, :void, :credit 14 | 15 | undef_method :authorize 16 | undef_method :capture 17 | undef_method :void 18 | undef_method :credit 19 | 20 | def test? 21 | Base.gateway_mode == :test 22 | end 23 | 24 | private 25 | def split(response) 26 | response.split('%') 27 | end 28 | end 29 | end 30 | end 31 | 32 | -------------------------------------------------------------------------------- /test/unit/country_code_test.rb: -------------------------------------------------------------------------------- 1 | require File.dirname(__FILE__) + '/../test_helper' 2 | 3 | class CountryCodeTest < Test::Unit::TestCase 4 | include ActiveMerchant 5 | 6 | def test_alpha2_country_code 7 | code = CountryCode.new('CA') 8 | assert_equal 'CA', code.value 9 | assert_equal 'CA', code.to_s 10 | assert_equal :alpha2, code.format 11 | end 12 | 13 | def test_lower_alpha2_country_code 14 | code = CountryCode.new('ca') 15 | assert_equal 'CA', code.value 16 | assert_equal 'CA', code.to_s 17 | assert_equal :alpha2, code.format 18 | end 19 | 20 | def test_alpha2_country_code 21 | code = CountryCode.new('CAN') 22 | assert_equal :alpha3, code.format 23 | end 24 | 25 | def test_numeric_code 26 | code = CountryCode.new('004') 27 | assert_equal :numeric, code.format 28 | end 29 | 30 | def test_invalid_code_format 31 | assert_raise(CountryCodeFormatError){ CountryCode.new('Canada') } 32 | end 33 | end 34 | -------------------------------------------------------------------------------- /test/unit/cvv_result_test.rb: -------------------------------------------------------------------------------- 1 | require File.dirname(__FILE__) + '/../test_helper' 2 | 3 | class CVVResultTest < Test::Unit::TestCase 4 | def test_nil_data 5 | result = CVVResult.new(nil) 6 | assert_nil result.code 7 | assert_nil result.message 8 | end 9 | 10 | def test_blank_data 11 | result = CVVResult.new('') 12 | assert_nil result.code 13 | assert_nil result.message 14 | end 15 | 16 | def test_successful_match 17 | result = CVVResult.new('M') 18 | assert_equal 'M', result.code 19 | assert_equal CVVResult.messages['M'], result.message 20 | end 21 | 22 | def test_failed_match 23 | result = CVVResult.new('N') 24 | assert_equal 'N', result.code 25 | assert_equal CVVResult.messages['N'], result.message 26 | end 27 | 28 | def test_to_hash 29 | result = CVVResult.new('M').to_hash 30 | assert_equal 'M', result['code'] 31 | assert_equal CVVResult.messages['M'], result['message'] 32 | end 33 | end -------------------------------------------------------------------------------- /lib/active_merchant/billing/response.rb: -------------------------------------------------------------------------------- 1 | module ActiveMerchant #:nodoc: 2 | module Billing #:nodoc: 3 | 4 | class Error < ActiveMerchantError #:nodoc: 5 | end 6 | 7 | class Response 8 | attr_reader :params, :message, :test, :authorization, :avs_result, :cvv_result 9 | 10 | def success? 11 | @success 12 | end 13 | 14 | def test? 15 | @test 16 | end 17 | 18 | def fraud_review? 19 | @fraud_review 20 | end 21 | 22 | def initialize(success, message, params = {}, options = {}) 23 | @success, @message, @params = success, message, params.stringify_keys 24 | @test = options[:test] || false 25 | @authorization = options[:authorization] 26 | @fraud_review = options[:fraud_review] 27 | @avs_result = AVSResult.new(options[:avs_result]).to_hash 28 | @cvv_result = CVVResult.new(options[:cvv_result]).to_hash 29 | end 30 | end 31 | end 32 | end 33 | -------------------------------------------------------------------------------- /test/unit/integrations/paypal_module_test.rb: -------------------------------------------------------------------------------- 1 | require File.dirname(__FILE__) + '/../../test_helper' 2 | 3 | class PaypalModuleTest < Test::Unit::TestCase 4 | include ActiveMerchant::Billing::Integrations 5 | 6 | def test_notification_method 7 | assert_instance_of Paypal::Notification, Paypal.notification('name=cody') 8 | end 9 | 10 | def test_test_mode 11 | ActiveMerchant::Billing::Base.integration_mode = :test 12 | assert_equal 'https://www.sandbox.paypal.com/cgi-bin/webscr', Paypal.service_url 13 | end 14 | 15 | def test_production_mode 16 | ActiveMerchant::Billing::Base.integration_mode = :production 17 | assert_equal 'https://www.paypal.com/cgi-bin/webscr', Paypal.service_url 18 | end 19 | 20 | def test_invalid_mode 21 | ActiveMerchant::Billing::Base.integration_mode = :zoomin 22 | assert_raise(StandardError){ Paypal.service_url } 23 | end 24 | 25 | def test_return_method 26 | assert_instance_of Paypal::Return, Paypal.return('name=cody') 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /lib/active_merchant/billing/integrations/return.rb: -------------------------------------------------------------------------------- 1 | module ActiveMerchant #:nodoc: 2 | module Billing #:nodoc: 3 | module Integrations #:nodoc: 4 | class Return 5 | attr_accessor :params 6 | 7 | def initialize(query_string) 8 | @params = parse(query_string) 9 | end 10 | 11 | # Successful by default. Overridden in the child class 12 | def success? 13 | true 14 | end 15 | 16 | def message 17 | 18 | end 19 | 20 | def parse(query_string) 21 | return {} if query_string.blank? 22 | 23 | query_string.split('&').inject({}) do |memo, chunk| 24 | next if chunk.empty? 25 | key, value = chunk.split('=', 2) 26 | next if key.empty? 27 | value = value.nil? ? nil : CGI.unescape(value) 28 | memo[CGI.unescape(key)] = value 29 | memo 30 | end 31 | end 32 | end 33 | end 34 | end 35 | end 36 | -------------------------------------------------------------------------------- /test/unit/response_test.rb: -------------------------------------------------------------------------------- 1 | require File.dirname(__FILE__) + '/../test_helper' 2 | 3 | class ResponseTest < Test::Unit::TestCase 4 | def test_response_success 5 | assert Response.new(true, 'message', :param => 'value').success? 6 | assert !Response.new(false, 'message', :param => 'value').success? 7 | end 8 | 9 | def test_get_params 10 | response = Response.new(true, 'message', :param => 'value') 11 | 12 | assert_equal ['param'], response.params.keys 13 | end 14 | 15 | def test_avs_result 16 | response = Response.new(true, 'message', {}, :avs_result => { :code => 'A', :street_match => 'Y', :zip_match => 'N' }) 17 | avs_result = response.avs_result 18 | assert_equal 'A', avs_result['code'] 19 | assert_equal AVSResult.messages['A'], avs_result['message'] 20 | end 21 | 22 | def test_cvv_result 23 | response = Response.new(true, 'message', {}, :cvv_result => 'M') 24 | cvv_result = response.cvv_result 25 | assert_equal 'M', cvv_result['code'] 26 | assert_equal CVVResult.messages['M'], cvv_result['message'] 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /test/remote/gateways/remote_trans_first_test.rb: -------------------------------------------------------------------------------- 1 | require File.dirname(__FILE__) + '/../../test_helper' 2 | 3 | class RemoteTransFirstTest < Test::Unit::TestCase 4 | 5 | def setup 6 | @gateway = TransFirstGateway.new(fixtures(:trans_first)) 7 | 8 | @credit_card = credit_card('4111111111111111') 9 | @amount = 100 10 | @options = { 11 | :order_id => generate_unique_id, 12 | :invoice => 'ActiveMerchant Sale', 13 | :billing_address => address 14 | } 15 | end 16 | 17 | def test_successful_purchase 18 | assert response = @gateway.purchase(@amount, @credit_card, @options) 19 | assert_equal 'test transaction', response.message 20 | assert response.test? 21 | assert_success response 22 | assert !response.authorization.blank? 23 | end 24 | 25 | def test_invalid_login 26 | gateway = TransFirstGateway.new( 27 | :login => '', 28 | :password => '' 29 | ) 30 | assert response = gateway.purchase(@amount, @credit_card, @options) 31 | assert_equal 'invalid account', response.message 32 | assert_failure response 33 | end 34 | end 35 | -------------------------------------------------------------------------------- /test/unit/gateways/bogus_test.rb: -------------------------------------------------------------------------------- 1 | require File.dirname(__FILE__) + '/../../test_helper' 2 | 3 | class BogusTest < Test::Unit::TestCase 4 | def setup 5 | @gateway = BogusGateway.new( 6 | :login => 'bogus', 7 | :password => 'bogus' 8 | ) 9 | 10 | @creditcard = credit_card('1') 11 | 12 | @response = ActiveMerchant::Billing::Response.new(true, "Transaction successful", :transid => BogusGateway::AUTHORIZATION) 13 | end 14 | 15 | def test_authorize 16 | @gateway.capture(1000, @creditcard) 17 | end 18 | 19 | def test_purchase 20 | @gateway.purchase(1000, @creditcard) 21 | end 22 | 23 | def test_credit 24 | @gateway.credit(1000, @response.params["transid"]) 25 | end 26 | 27 | def test_store 28 | @gateway.store(@creditcard) 29 | end 30 | 31 | def test_unstore 32 | @gateway.unstore('1') 33 | end 34 | 35 | def test_supported_countries 36 | assert_equal ['US'], BogusGateway.supported_countries 37 | end 38 | 39 | def test_supported_card_types 40 | assert_equal [:bogus], BogusGateway.supported_cardtypes 41 | end 42 | end 43 | -------------------------------------------------------------------------------- /MIT-LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2005 Tobias Luetke 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /lib/active_merchant/billing/cvv_result.rb: -------------------------------------------------------------------------------- 1 | module ActiveMerchant 2 | module Billing 3 | # Result of the Card Verification Value check 4 | # http://www.bbbonline.org/eExport/doc/MerchantGuide_cvv2.pdf 5 | # Check additional codes from cybersource website 6 | class CVVResult 7 | 8 | MESSAGES = { 9 | 'D' => 'Suspicious transaction', 10 | 'I' => 'Failed data validation check', 11 | 'M' => 'Match', 12 | 'N' => 'No Match', 13 | 'P' => 'Not Processed', 14 | 'S' => 'Should have been present', 15 | 'U' => 'Issuer unable to process request', 16 | 'X' => 'Card does not support verification' 17 | } 18 | 19 | def self.messages 20 | MESSAGES 21 | end 22 | 23 | attr_reader :code, :message 24 | 25 | def initialize(code) 26 | @code = code.upcase unless code.blank? 27 | @message = MESSAGES[@code] 28 | end 29 | 30 | def to_hash 31 | { 32 | 'code' => code, 33 | 'message' => message 34 | } 35 | end 36 | end 37 | end 38 | end -------------------------------------------------------------------------------- /lib/active_merchant/billing/gateways/payflow/payflow_express_response.rb: -------------------------------------------------------------------------------- 1 | module ActiveMerchant #:nodoc: 2 | module Billing #:nodoc: 3 | class PayflowExpressResponse < Response 4 | def email 5 | @params['e_mail'] 6 | end 7 | 8 | def full_name 9 | "#{@params['name']} #{@params['lastname']}" 10 | end 11 | 12 | def token 13 | @params['token'] 14 | end 15 | 16 | def payer_id 17 | @params['payer_id'] 18 | end 19 | 20 | # Really the shipping country, but it is all the information provided 21 | def payer_country 22 | address['country'] 23 | end 24 | 25 | def address 26 | { 'name' => full_name, 27 | 'company' => nil, 28 | 'address1' => @params['street'], 29 | 'address2' => nil, 30 | 'city' => @params['city'], 31 | 'state' => @params['state'], 32 | 'country' => @params['country'], 33 | 'zip' => @params['zip'], 34 | 'phone' => nil 35 | } 36 | end 37 | end 38 | end 39 | end -------------------------------------------------------------------------------- /lib/active_merchant/billing/gateways/paypal/paypal_express_response.rb: -------------------------------------------------------------------------------- 1 | module ActiveMerchant #:nodoc: 2 | module Billing #:nodoc: 3 | class PaypalExpressResponse < Response 4 | def email 5 | @params['payer'] 6 | end 7 | 8 | def name 9 | [@params['first_name'], @params['middle_name'], @params['last_name']].compact.join(' ') 10 | end 11 | 12 | def token 13 | @params['token'] 14 | end 15 | 16 | def payer_id 17 | @params['payer_id'] 18 | end 19 | 20 | def payer_country 21 | @params['payer_country'] 22 | end 23 | 24 | def address 25 | { 'name' => @params['name'], 26 | 'company' => @params['payer_business'], 27 | 'address1' => @params['street1'], 28 | 'address2' => @params['street2'], 29 | 'city' => @params['city_name'], 30 | 'state' => @params['state_or_province'], 31 | 'country' => @params['country'], 32 | 'zip' => @params['postal_code'], 33 | 'phone' => nil 34 | } 35 | end 36 | end 37 | end 38 | end -------------------------------------------------------------------------------- /lib/active_merchant/billing/gateways/paypal_nv/paypal_express_nv_response.rb: -------------------------------------------------------------------------------- 1 | module ActiveMerchant #:nodoc: 2 | module Billing #:nodoc: 3 | class PaypalExpressNvResponse < Response 4 | def email 5 | @params['email'] 6 | end 7 | 8 | def name 9 | [@params['firstname'], @params['middlename'], @params['lastname']].compact.join(' ') 10 | end 11 | 12 | def token 13 | @params['token'] 14 | end 15 | 16 | def payer_id 17 | @params['payerid'] 18 | end 19 | 20 | def payer_country 21 | @params['payer_country'] 22 | end 23 | 24 | def address 25 | { 'name' => self.name, 26 | 'company' => @params['business'], 27 | 'address1' => @params['shiptostreet'], 28 | 'address2' => @params['shiptostreet2'], 29 | 'city' => @params['shiptocity'], 30 | 'state' => @params['shiptostate'], 31 | 'country' => @params['shiptocountrycode'], 32 | 'zip' => @params['shiptozip'], 33 | 'phone' => @params['phonenum'], 34 | } 35 | end 36 | end 37 | end 38 | end 39 | -------------------------------------------------------------------------------- /lib/active_merchant/billing/gateways/payflow_nv/payflow_express_nv_response.rb: -------------------------------------------------------------------------------- 1 | module ActiveMerchant #:nodoc: 2 | module Billing #:nodoc: 3 | class PayflowExpressNvResponse < Response 4 | def email 5 | @params['email'] 6 | end 7 | 8 | def full_name 9 | "#{@params['firstname']} #{@params['lastname']}" 10 | end 11 | 12 | def token 13 | @params['token'] 14 | end 15 | 16 | def payer_id 17 | @params['payerid'] 18 | end 19 | 20 | # Really the shipping country, but it is all the information provided 21 | def payer_country 22 | address['country'] 23 | end 24 | 25 | def address 26 | { 'name' => full_name, 27 | 'company' => @params['business'], 28 | 'address1' => @params['shiptostreet'], 29 | 'address2' => nil, 30 | 'city' => @params['shiptocity'], 31 | 'state' => @params['shiptostate'], 32 | 'country' => @params['shiptocountry'], 33 | 'zip' => @params['shiptozip'], 34 | 'phone' => nil 35 | } 36 | end 37 | end 38 | end 39 | end 40 | -------------------------------------------------------------------------------- /generators/integration/templates/notification_test.rb: -------------------------------------------------------------------------------- 1 | require File.dirname(__FILE__) + '/../../../test_helper' 2 | 3 | class <%= class_name %>NotificationTest < Test::Unit::TestCase 4 | include ActiveMerchant::Billing::Integrations 5 | 6 | def setup 7 | @<%= name %> = <%= class_name %>::Notification.new(http_raw_data) 8 | end 9 | 10 | def test_accessors 11 | assert @<%= name %>.complete? 12 | assert_equal "", @<%= name %>.status 13 | assert_equal "", @<%= name %>.transaction_id 14 | assert_equal "", @<%= name %>.item_id 15 | assert_equal "", @<%= name %>.gross 16 | assert_equal "", @<%= name %>.currency 17 | assert_equal "", @<%= name %>.received_at 18 | assert @<%= name %>.test? 19 | end 20 | 21 | def test_compositions 22 | assert_equal Money.new(3166, 'USD'), @<%= name %>.amount 23 | end 24 | 25 | # Replace with real successful acknowledgement code 26 | def test_acknowledgement 27 | 28 | end 29 | 30 | def test_send_acknowledgement 31 | end 32 | 33 | def test_respond_to_acknowledge 34 | assert @<%= name %>.respond_to?(:acknowledge) 35 | end 36 | 37 | private 38 | def http_raw_data 39 | "" 40 | end 41 | end 42 | -------------------------------------------------------------------------------- /gem-public_cert.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDNjCCAh6gAwIBAgIBADANBgkqhkiG9w0BAQUFADBBMRMwEQYDVQQDDApjb2R5 3 | ZmF1c2VyMRUwEwYKCZImiZPyLGQBGRYFZ21haWwxEzARBgoJkiaJk/IsZAEZFgNj 4 | b20wHhcNMDcwMjIyMTcyMTI3WhcNMDgwMjIyMTcyMTI3WjBBMRMwEQYDVQQDDApj 5 | b2R5ZmF1c2VyMRUwEwYKCZImiZPyLGQBGRYFZ21haWwxEzARBgoJkiaJk/IsZAEZ 6 | FgNjb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC6T4Iqt5iWvAlU 7 | iXI6L8UO0URQhIC65X/gJ9hL/x4lwSl/ckVm/R/bPrJGmifT+YooFv824N3y/TIX 8 | 25o/lZtRj1TUZJK4OCb0aVzosQVxBHSe6rLmxO8cItNTMOM9wn3thaITFrTa1DOQ 9 | O3wqEjvW2L6VMozVfK1MfjL9IGgy0rCnl+2g4Gh4jDDpkLfnMG5CWI6cTCf3C1ye 10 | ytOpWgi0XpOEy8nQWcFmt/KCQ/kFfzBo4QxqJi54b80842EyvzWT9OB7Oew/CXZG 11 | F2yIHtiYxonz6N09vvSzq4CvEuisoUFLKZnktndxMEBKwJU3XeSHAbuS7ix40OKO 12 | WKuI54fHAgMBAAGjOTA3MAkGA1UdEwQCMAAwCwYDVR0PBAQDAgSwMB0GA1UdDgQW 13 | BBR9QQpefI3oDCAxiqJW/3Gg6jI6qjANBgkqhkiG9w0BAQUFAAOCAQEAs0lX26O+ 14 | HpyMp7WL+SgZuM8k76AjfOHuKajl2GEn3S8pWYGpsa0xu07HtehJhKLiavrfUYeE 15 | qlFtyYMUyOh6/1S2vfkH6VqjX7mWjoi7XKHW/99fkMS40B5SbN+ypAUst+6c5R84 16 | w390mjtLHpdDE6WQYhS6bFvBN53vK6jG3DLyCJc0K9uMQ7gdHWoxq7RnG92ncQpT 17 | ThpRA+fky5Xt2Q63YJDnJpkYAz79QIama1enSnd4jslKzSl89JS2luq/zioPe/Us 18 | hbyalWR1+HrhgPoSPq7nk+s2FQUBJ9UZFK1lgMzho/4fZgzJwbu+cO8SNuaLS/bj 19 | hPaSTyVU0yCSnw== 20 | -----END CERTIFICATE----- 21 | -------------------------------------------------------------------------------- /generators/integration/templates/helper.rb: -------------------------------------------------------------------------------- 1 | module ActiveMerchant #:nodoc: 2 | module Billing #:nodoc: 3 | module Integrations #:nodoc: 4 | module <%= class_name %> 5 | class Helper < ActiveMerchant::Billing::Integrations::Helper 6 | # Replace with the real mapping 7 | mapping :account, '' 8 | mapping :amount, '' 9 | 10 | mapping :order, '' 11 | 12 | mapping :customer, :first_name => '', 13 | :last_name => '', 14 | :email => '', 15 | :phone => '' 16 | 17 | mapping :billing_address, :city => '', 18 | :address1 => '', 19 | :address2 => '', 20 | :state => '', 21 | :zip => '', 22 | :country => '' 23 | 24 | mapping :notify_url, '' 25 | mapping :return_url, '' 26 | mapping :cancel_return_url, '' 27 | mapping :description, '' 28 | mapping :tax, '' 29 | mapping :shipping, '' 30 | end 31 | end 32 | end 33 | end 34 | end 35 | -------------------------------------------------------------------------------- /test/remote/gateways/remote_secure_pay_au_test.rb: -------------------------------------------------------------------------------- 1 | require File.dirname(__FILE__) + '/../../test_helper' 2 | 3 | class RemoteSecurePayAuTest < Test::Unit::TestCase 4 | 5 | def setup 6 | @gateway = SecurePayAuGateway.new(fixtures(:secure_pay_au)) 7 | 8 | @amount = 100 9 | @credit_card = credit_card('4444333322221111') 10 | 11 | @options = { 12 | :order_id => '1', 13 | :billing_address => address, 14 | :description => 'Store Purchase' 15 | } 16 | end 17 | 18 | def test_successful_purchase 19 | assert response = @gateway.purchase(@amount, @credit_card, @options) 20 | assert_success response 21 | assert_equal 'Approved', response.message 22 | end 23 | 24 | def test_unsuccessful_purchase 25 | @credit_card.year = '2005' 26 | assert response = @gateway.purchase(@amount, @credit_card, @options) 27 | assert_failure response 28 | assert_equal 'CARD EXPIRED', response.message 29 | end 30 | 31 | def test_invalid_login 32 | gateway = SecurePayAuGateway.new( 33 | :login => '', 34 | :password => '' 35 | ) 36 | assert response = gateway.purchase(@amount, @credit_card, @options) 37 | assert_failure response 38 | assert_equal "Invalid merchant ID", response.message 39 | end 40 | end 41 | -------------------------------------------------------------------------------- /test/remote/gateways/remote_pay_secure_test.rb: -------------------------------------------------------------------------------- 1 | require File.dirname(__FILE__) + '/../../test_helper' 2 | 3 | class RemotePaySecureTest < Test::Unit::TestCase 4 | 5 | def setup 6 | @gateway = PaySecureGateway.new(fixtures(:pay_secure)) 7 | 8 | @credit_card = credit_card('4000100011112224') 9 | @options = { 10 | :billing_address => address, 11 | :order_id => generate_unique_id 12 | } 13 | @amount = 100 14 | end 15 | 16 | def test_successful_purchase 17 | assert response = @gateway.purchase(@amount, @credit_card, @options) 18 | assert_success response 19 | assert_equal PaySecureGateway::SUCCESS_MESSAGE, response.message 20 | assert response.test? 21 | end 22 | 23 | def test_unsuccessful_purchase 24 | @credit_card.year = '2006' 25 | assert response = @gateway.purchase(@amount, @credit_card, @options) 26 | assert_equal 'Declined, card expired', response.message 27 | assert_failure response 28 | end 29 | 30 | def test_invalid_login 31 | gateway = PaySecureGateway.new( 32 | :login => '', 33 | :password => '' 34 | ) 35 | assert response = gateway.purchase(@amount, @credit_card, @options) 36 | assert_equal "MissingField: 'MERCHANT_ID'", response.message 37 | assert_failure response 38 | end 39 | end 40 | -------------------------------------------------------------------------------- /test/remote/gateways/remote_secure_pay_tech_test.rb: -------------------------------------------------------------------------------- 1 | require File.dirname(__FILE__) + '/../../test_helper' 2 | 3 | class RemoteSecurePayTechTest < Test::Unit::TestCase 4 | $verbose = true 5 | 6 | def setup 7 | @gateway = SecurePayTechGateway.new(fixtures(:secure_pay_tech)) 8 | 9 | @accepted_amount = 10000 10 | @declined_amount = 10075 11 | 12 | @credit_card = credit_card('4987654321098769', :month => '5', :year => '2013') 13 | @options = { :billing_address => address } 14 | end 15 | 16 | def test_successful_purchase 17 | assert response = @gateway.purchase(@accepted_amount, @credit_card, @options) 18 | assert_equal 'Transaction OK', response.message 19 | assert_success response 20 | end 21 | 22 | def test_unsuccessful_purchase 23 | assert response = @gateway.purchase(@declined_amount, @credit_card, @options) 24 | assert_equal 'Card declined', response.message 25 | assert_failure response 26 | end 27 | 28 | def test_invalid_login 29 | gateway = SecurePayTechGateway.new( 30 | :login => 'foo', 31 | :password => 'bar' 32 | ) 33 | assert response = gateway.purchase(@accepted_amount, @credit_card, @options) 34 | assert_equal 'Bad or malformed request', response.message 35 | assert_failure response 36 | end 37 | end 38 | -------------------------------------------------------------------------------- /lib/active_merchant/billing/gateways/modern_payments.rb: -------------------------------------------------------------------------------- 1 | require File.dirname(__FILE__) + '/modern_payments_cim' 2 | 3 | module ActiveMerchant #:nodoc: 4 | module Billing #:nodoc: 5 | class ModernPaymentsGateway < Gateway 6 | self.supported_countries = ModernPaymentsCimGateway.supported_countries 7 | self.supported_cardtypes = ModernPaymentsCimGateway.supported_cardtypes 8 | self.homepage_url = ModernPaymentsCimGateway.homepage_url 9 | self.display_name = ModernPaymentsCimGateway.display_name 10 | 11 | def initialize(options = {}) 12 | requires!(options, :login, :password) 13 | @options = options 14 | super 15 | end 16 | 17 | def purchase(money, credit_card, options = {}) 18 | customer_response = cim.create_customer(options) 19 | return customer_response unless customer_response.success? 20 | 21 | customer_id = customer_response.params["create_customer_result"] 22 | 23 | card_response = cim.modify_customer_credit_card(customer_id, credit_card) 24 | return card_response unless card_response.success? 25 | 26 | cim.authorize_credit_card_payment(customer_id, money) 27 | end 28 | 29 | private 30 | def cim 31 | @cim ||= ModernPaymentsCimGateway.new(@options) 32 | end 33 | end 34 | end 35 | end 36 | 37 | -------------------------------------------------------------------------------- /test/unit/integrations/returns/two_checkout_return_test.rb: -------------------------------------------------------------------------------- 1 | require File.dirname(__FILE__) + '/../../../test_helper' 2 | 3 | class TwoCheckoutReturnTest < Test::Unit::TestCase 4 | include ActiveMerchant::Billing::Integrations 5 | 6 | def test_successful_purchase 7 | r = TwoCheckout::Return.new(successful_purchase) 8 | assert r.success? 9 | end 10 | 11 | def test_pending_purchase 12 | r = TwoCheckout::Return.new(failed_purchase) 13 | assert !r.success? 14 | end 15 | 16 | private 17 | def successful_purchase 18 | 'sid=1232919&fixed=Y&key=C17C887BDCCD0499264FAE9F578CCA66&state=ON&email=codyfauser%40gmail.com&street_address=138+Clarence+St.&city=Ottawa&cart_order_id=9&order_number=3860340141&merchant_order_id=%231009&country=CAN&ip_country=&cart_id=9&lang=en&demo=Y&pay_method=CC&total=118.30&phone=%28613%29555-5555+&credit_card_processed=Y&zip=K1N5P8&street_address2=Apartment+1&card_holder_name=Cody++Fauser' 19 | end 20 | 21 | def failed_purchase 22 | 'sid=1232919&fixed=Y&key=C17C887BDCCD0499264FAE9F578CCA66&state=ON&email=codyfauser%40gmail.com&street_address=138+Clarence+St.&city=Ottawa&cart_order_id=9&order_number=3860340141&merchant_order_id=%231009&country=CAN&ip_country=&cart_id=9&lang=en&demo=Y&pay_method=CC&total=118.30&phone=%28613%29555-5555+&credit_card_processed=K&zip=K1N5P8&street_address2=Apartment+1&card_holder_name=Cody++Fauser' 23 | end 24 | end -------------------------------------------------------------------------------- /test/remote/gateways/remote_viaklix_test.rb: -------------------------------------------------------------------------------- 1 | require File.dirname(__FILE__) + '/../../test_helper' 2 | 3 | class RemoteViaklixTest < Test::Unit::TestCase 4 | def setup 5 | @gateway = ViaklixGateway.new(fixtures(:viaklix)) 6 | 7 | @credit_card = credit_card 8 | @bad_credit_card = credit_card('invalid') 9 | 10 | @options = { 11 | :order_id => '#1000.1', 12 | :email => "paul@domain.com", 13 | :description => 'Test Transaction', 14 | :billing_address => address 15 | } 16 | @amount = 100 17 | end 18 | 19 | def test_successful_purchase 20 | assert response = @gateway.purchase(@amount, @credit_card, @options) 21 | 22 | assert_success response 23 | assert response.test? 24 | assert_equal 'APPROVED', response.message 25 | assert response.authorization 26 | end 27 | 28 | def test_failed_purchase 29 | assert response = @gateway.purchase(@amount, @bad_credit_card, @options) 30 | 31 | assert_failure response 32 | assert response.test? 33 | assert_equal 'The Credit Card Number supplied in the authorization request appears invalid.', response.message 34 | end 35 | 36 | def test_credit 37 | assert purchase = @gateway.purchase(@amount, @credit_card, @options) 38 | assert_success purchase 39 | 40 | assert credit = @gateway.credit(@amount, @credit_card) 41 | assert_success credit 42 | end 43 | end -------------------------------------------------------------------------------- /test/remote/integrations/remote_gestpay_integration_test.rb: -------------------------------------------------------------------------------- 1 | require File.dirname(__FILE__) + '/../../test_helper' 2 | 3 | class RemoteGestpayIntegrationTest < Test::Unit::TestCase 4 | include ActiveMerchant::Billing::Integrations 5 | 6 | def setup 7 | # Your Gestpay ShopLogin 8 | @shop_login = 'SHOPLOGIN' 9 | 10 | @helper = Gestpay::Helper.new('order-500', @shop_login, :amount => '5.00', :currency => 'EUR') 11 | end 12 | 13 | def test_get_encryption_string 14 | # Extra fields don't work yet 15 | # @helper.customer :first_name => 'Cody', :last_name => 'Fauser', :email => 'codyfauser@gmail.com' 16 | response = @helper.send(:get_encrypted_string) 17 | assert !response.blank? 18 | end 19 | 20 | def test_get_encryption_string_fails 21 | @helper = Gestpay::Helper.new('order-500','99999999', :amount => '5.00', :currency => 'EUR') 22 | assert_raise(StandardError) do 23 | assert @helper.send(:get_encrypted_string).blank? 24 | end 25 | end 26 | 27 | def test_unknown_shop_for_decryption_request 28 | assert_raise(StandardError) do 29 | Gestpay::Notification.new(raw_query_string) 30 | end 31 | end 32 | 33 | private 34 | def raw_query_string 35 | "a=900000&b=F7DEB36478FD84760F9134F23C922697272D57DE6D4518EB9B4D468B769D9A3A8071B6EB160B35CB412FC1820C7CC12D17B3141855B1ED55468613702A2E213DDE9DE5B0209E13C416448AE833525959F05693172D7F0656" 36 | end 37 | end 38 | -------------------------------------------------------------------------------- /test/unit/gateways/secure_pay_tech_test.rb: -------------------------------------------------------------------------------- 1 | require File.dirname(__FILE__) + '/../../test_helper' 2 | 3 | class SecurePayTechTest < Test::Unit::TestCase 4 | def setup 5 | @gateway = SecurePayTechGateway.new( 6 | :login => 'x', 7 | :password => 'y' 8 | ) 9 | 10 | @amount = 100 11 | @credit_card = credit_card('4987654321098769') 12 | @options = { 13 | :billing_address => address 14 | } 15 | end 16 | 17 | def test_successful_purchase 18 | @gateway.expects(:ssl_post).returns(successful_purchase_response) 19 | 20 | assert response = @gateway.purchase(@amount, @credit_card, @options) 21 | assert_instance_of Response, response 22 | assert_success response 23 | assert response.test? 24 | assert_equal '4--120119220646821', response.authorization 25 | end 26 | 27 | def test_unsuccessful_purchase 28 | @gateway.expects(:ssl_post).returns(unsuccessful_purchase_response) 29 | 30 | assert response = @gateway.purchase(@amount, @credit_card, @options) 31 | assert_instance_of Response, response 32 | assert_failure response 33 | assert response.test? 34 | end 35 | 36 | private 37 | def successful_purchase_response 38 | "1,4--120119220646821,000000014511,23284,014511,20080125\r\n" 39 | end 40 | 41 | def unsuccessful_purchase_response 42 | "4,4--120119180936527,000000014510,23283,014510,20080125\r\n" 43 | end 44 | end 45 | -------------------------------------------------------------------------------- /lib/active_merchant/billing/integrations/paypal.rb: -------------------------------------------------------------------------------- 1 | require 'active_merchant/billing/integrations/paypal/helper.rb' 2 | require 'active_merchant/billing/integrations/paypal/notification.rb' 3 | require 'active_merchant/billing/integrations/paypal/return.rb' 4 | 5 | module ActiveMerchant #:nodoc: 6 | module Billing #:nodoc: 7 | module Integrations #:nodoc: 8 | module Paypal 9 | 10 | # Overwrite this if you want to change the Paypal test url 11 | mattr_accessor :test_url 12 | self.test_url = 'https://www.sandbox.paypal.com/cgi-bin/webscr' 13 | 14 | # Overwrite this if you want to change the Paypal production url 15 | mattr_accessor :production_url 16 | self.production_url = 'https://www.paypal.com/cgi-bin/webscr' 17 | 18 | def self.service_url 19 | mode = ActiveMerchant::Billing::Base.integration_mode 20 | case mode 21 | when :production 22 | self.production_url 23 | when :test 24 | self.test_url 25 | else 26 | raise StandardError, "Integration mode set to an invalid value: #{mode}" 27 | end 28 | end 29 | 30 | def self.notification(post) 31 | Notification.new(post) 32 | end 33 | 34 | def self.return(query_string) 35 | Return.new(query_string) 36 | end 37 | end 38 | end 39 | end 40 | end 41 | -------------------------------------------------------------------------------- /test/unit/post_data_test.rb: -------------------------------------------------------------------------------- 1 | require File.dirname(__FILE__) + '/../test_helper' 2 | 3 | class MyPost < PostData 4 | self.required_fields = [ :ccnumber, :ccexp, :firstname, :lastname, :username, :password, :order_id, :key, :time ] 5 | end 6 | 7 | class PostDataTest < Test::Unit::TestCase 8 | 9 | def setup 10 | 11 | end 12 | 13 | def teardown 14 | PostData.required_fields = [] 15 | end 16 | 17 | def test_element_assignment 18 | name = 'Cody Fauser' 19 | post = PostData.new 20 | 21 | post[:name] = name 22 | assert_equal name, post[:name] 23 | end 24 | 25 | def test_ignore_blank_fields 26 | post = PostData.new 27 | assert_equal 0, post.keys.size 28 | 29 | post[:name] = '' 30 | assert_equal 0, post.keys.size 31 | 32 | post[:name] = nil 33 | assert_equal 0, post.keys.size 34 | end 35 | 36 | def test_dont_ignore_required_blank_fields 37 | PostData.required_fields = [ :name ] 38 | post = PostData.new 39 | 40 | assert_equal 0, post.keys.size 41 | 42 | post[:name] = '' 43 | assert_equal 1, post.keys.size 44 | assert_equal '', post[:name] 45 | 46 | post[:name] = nil 47 | assert_equal 1, post.keys.size 48 | assert_nil post[:name] 49 | end 50 | 51 | def test_subclass 52 | post = MyPost.new 53 | assert_equal [ :ccnumber, :ccexp, :firstname, :lastname, :username, :password, :order_id, :key, :time ], post.required_fields 54 | end 55 | end -------------------------------------------------------------------------------- /lib/active_merchant/billing/integrations/gestpay/common.rb: -------------------------------------------------------------------------------- 1 | module ActiveMerchant #:nodoc: 2 | module Billing #:nodoc: 3 | module Integrations #:nodoc: 4 | module Gestpay 5 | module Common 6 | VERSION = "2.0" 7 | ENCRYPTION_PATH = "/CryptHTTPS/Encrypt.asp" 8 | DECRYPTION_PATH = "/CryptHTTPS/Decrypt.asp" 9 | DELIMITER = '*P1*' 10 | 11 | CURRENCY_MAPPING = { 12 | 'EUR' => '242', 13 | 'ITL' => '18', 14 | 'BRL' => '234', 15 | 'USD' => '1', 16 | 'JPY' => '71', 17 | 'HKD' => '103' 18 | } 19 | 20 | def parse_response(response) 21 | case response 22 | when /#cryptstring#(.*)#\/cryptstring#/, /#decryptstring#(.*)#\/decryptstring#/ 23 | $1 24 | when /#error#(.*)#\/error#/ 25 | raise StandardError, "An error occurred retrieving the encrypted string from GestPay: #{$1}" 26 | else 27 | raise StandardError, "No response was received by GestPay" 28 | end 29 | end 30 | 31 | def ssl_get(url, path) 32 | uri = URI.parse(url) 33 | site = Net::HTTP.new(uri.host, uri.port) 34 | site.use_ssl = true 35 | site.verify_mode = OpenSSL::SSL::VERIFY_NONE 36 | site.get(path).body 37 | end 38 | end 39 | end 40 | end 41 | end 42 | end -------------------------------------------------------------------------------- /generators/gateway/templates/gateway_test.rb: -------------------------------------------------------------------------------- 1 | require File.dirname(__FILE__) + '/../../test_helper' 2 | 3 | class <%= class_name %>Test < Test::Unit::TestCase 4 | def setup 5 | @gateway = <%= class_name %>Gateway.new( 6 | :login => 'login', 7 | :password => 'password' 8 | ) 9 | 10 | @credit_card = credit_card 11 | @amount = 100 12 | 13 | @options = { 14 | :order_id => '1', 15 | :billing_address => address, 16 | :description => 'Store Purchase' 17 | } 18 | end 19 | 20 | def test_successful_purchase 21 | @gateway.expects(:ssl_post).returns(successful_purchase_response) 22 | 23 | assert response = @gateway.purchase(@amount, @credit_card, @options) 24 | assert_instance_of 25 | assert_success response 26 | 27 | # Replace with authorization number from the successful response 28 | assert_equal '', response.authorization 29 | assert response.test? 30 | end 31 | 32 | def test_unsuccessful_request 33 | @gateway.expects(:ssl_post).returns(failed_purchase_response) 34 | 35 | assert response = @gateway.purchase(@amount, @credit_card, @options) 36 | assert_failure response 37 | assert response.test? 38 | end 39 | 40 | private 41 | 42 | # Place raw successful response from gateway here 43 | def successful_purchase_response 44 | end 45 | 46 | # Place raw failed response from gateway here 47 | def failed_purcahse_response 48 | end 49 | end 50 | -------------------------------------------------------------------------------- /test/unit/integrations/action_view_helper_test.rb: -------------------------------------------------------------------------------- 1 | require File.dirname(__FILE__) + '/../../test_helper' 2 | 3 | class ActionViewHelperTest < Test::Unit::TestCase 4 | include ActiveMerchant::Billing::Integrations::ActionViewHelper 5 | include ActionView::Helpers::FormHelper 6 | include ActionView::Helpers::FormTagHelper 7 | include ActionView::Helpers::UrlHelper 8 | include ActionView::Helpers::TagHelper 9 | include ActionView::Helpers::TextHelper 10 | 11 | def setup 12 | @controller = Class.new do 13 | attr_reader :url_for_options 14 | def url_for(options, *parameters_for_method_reference) 15 | @url_for_options = options 16 | end 17 | end 18 | @controller = @controller.new 19 | end 20 | 21 | 22 | def test_basic_payment_service 23 | _erbout = '' 24 | 25 | payment_service_for('order-1','test', :service => :bogus){} 26 | 27 | expected = [ 28 | '
" 32 | ] 33 | 34 | _erbout.each_line do |line| 35 | assert expected.include?(line.chomp), "Failed to match #{line}" 36 | end 37 | end 38 | 39 | def test_payment_service_no_block_given 40 | assert_raise(ArgumentError){ payment_service_for } 41 | end 42 | 43 | protected 44 | def protect_against_forgery? 45 | false 46 | end 47 | end 48 | -------------------------------------------------------------------------------- /lib/support/gateway_support.rb: -------------------------------------------------------------------------------- 1 | require 'rubygems' 2 | require 'active_support' 3 | require 'lib/active_merchant' 4 | 5 | 6 | class GatewaySupport #:nodoc: 7 | ACTIONS = [:purchase, :authorize, :capture, :void, :credit, :recurring] 8 | 9 | include ActiveMerchant::Billing 10 | 11 | attr_reader :gateways 12 | 13 | def initialize 14 | @gateways = Gateway.implementations.sort_by(&:name) 15 | @gateways.delete(ActiveMerchant::Billing::BogusGateway) 16 | end 17 | 18 | def each_gateway 19 | @gateways.each{|g| yield g } 20 | end 21 | 22 | def features 23 | width = 15 24 | 25 | print "Name".center(width + 20) 26 | ACTIONS.each{|f| print "#{f.to_s.capitalize.center(width)}" } 27 | puts 28 | 29 | each_gateway do |g| 30 | print "#{g.display_name.ljust(width + 20)}" 31 | ACTIONS.each do |f| 32 | print "#{(g.instance_methods.include?(f.to_s) ? "Y" : "N").center(width)}" 33 | end 34 | puts 35 | end 36 | end 37 | 38 | def to_rdoc 39 | each_gateway do |g| 40 | puts "* {#{g.display_name}}[#{g.homepage_url}] - #{g.supported_countries.join(', ')}" 41 | end 42 | end 43 | 44 | def to_textile 45 | each_gateway do |g| 46 | puts %/ * "#{g.display_name}":#{g.homepage_url} [#{g.supported_countries.join(', ')}]/ 47 | end 48 | end 49 | 50 | def to_s 51 | each_gateway do |g| 52 | puts "#{g.display_name} - #{g.homepage_url} [#{g.supported_countries.join(', ')}]" 53 | end 54 | end 55 | end 56 | 57 | 58 | -------------------------------------------------------------------------------- /test/remote/gateways/remote_modern_payments_test.rb: -------------------------------------------------------------------------------- 1 | require File.dirname(__FILE__) + '/../../test_helper' 2 | 3 | class RemoteModernPaymentTest < Test::Unit::TestCase 4 | 5 | 6 | def setup 7 | @gateway = ModernPaymentsGateway.new(fixtures(:modern_payments)) 8 | 9 | @amount = 100 10 | @credit_card = credit_card('4111111111111111') 11 | @declined_card = credit_card('4000000000000000') 12 | 13 | @options = { 14 | :order_id => '1', 15 | :billing_address => address, 16 | :description => 'Store Purchase' 17 | } 18 | end 19 | 20 | def test_successful_purchase 21 | assert response = @gateway.purchase(@amount, @credit_card, @options) 22 | assert_success response 23 | assert_match /RESPONSECODE=A/, response.params["auth_string"] 24 | assert_equal ModernPaymentsCimGateway::SUCCESS_MESSAGE, response.message 25 | end 26 | 27 | def test_unsuccessful_purchase 28 | assert response = @gateway.purchase(@amount, @declined_card, @options) 29 | assert_success response 30 | assert_match /RESPONSECODE=D/, response.params["auth_string"] 31 | assert_equal ModernPaymentsCimGateway::SUCCESS_MESSAGE, response.message 32 | end 33 | 34 | def test_invalid_login 35 | gateway = ModernPaymentsGateway.new( 36 | :login => '', 37 | :password => '' 38 | ) 39 | assert response = gateway.purchase(@amount, @credit_card, @options) 40 | assert_failure response 41 | assert_equal ModernPaymentsCimGateway::ERROR_MESSAGE, response.message 42 | end 43 | end 44 | -------------------------------------------------------------------------------- /lib/active_merchant/billing/integrations/hi_trust/notification.rb: -------------------------------------------------------------------------------- 1 | require 'net/http' 2 | 3 | module ActiveMerchant #:nodoc: 4 | module Billing #:nodoc: 5 | module Integrations #:nodoc: 6 | module HiTrust 7 | class Notification < ActiveMerchant::Billing::Integrations::Notification 8 | SUCCESS = '00' 9 | 10 | self.production_ips = [ '203.75.242.8' ] 11 | 12 | def complete? 13 | status == 'Completed' 14 | end 15 | 16 | def transaction_id 17 | params['authRRN'] 18 | end 19 | 20 | def item_id 21 | params['ordernumber'] 22 | end 23 | 24 | def received_at 25 | Time.parse(params['orderdate']) rescue nil 26 | end 27 | 28 | def currency 29 | params['currency'] 30 | end 31 | 32 | def gross 33 | sprintf("%.2f", gross_cents.to_f / 100) 34 | end 35 | 36 | def gross_cents 37 | params['approveamount'].to_i 38 | end 39 | 40 | def account 41 | params['storeid'] 42 | end 43 | 44 | def status 45 | params['retcode'] == SUCCESS ? 'Completed' : 'Failed' 46 | end 47 | 48 | def test? 49 | ActiveMerchant::Billing::Base.integration_mode == :test 50 | end 51 | 52 | def acknowledge 53 | true 54 | end 55 | end 56 | end 57 | end 58 | end 59 | end 60 | -------------------------------------------------------------------------------- /test/unit/validateable_test.rb: -------------------------------------------------------------------------------- 1 | require File.dirname(__FILE__) + '/../test_helper' 2 | 3 | class Dood 4 | include ActiveMerchant::Validateable 5 | 6 | attr_accessor :name, :email, :country 7 | 8 | def validate 9 | errors.add "name", "cannot be empty" if name.blank? 10 | errors.add "email", "cannot be empty" if email.blank? 11 | errors.add_to_base "The country cannot be blank" if country.blank? 12 | end 13 | 14 | end 15 | 16 | class ValidateableTest < Test::Unit::TestCase 17 | include ActiveMerchant 18 | 19 | def setup 20 | @dood = Dood.new 21 | end 22 | 23 | def test_validation 24 | assert ! @dood.valid? 25 | assert ! @dood.errors.empty? 26 | end 27 | 28 | def test_assigns 29 | @dood = Dood.new(:name => "tobi", :email => "tobi@neech.de", :country => 'DE') 30 | 31 | assert_equal "tobi", @dood.name 32 | assert_equal "tobi@neech.de", @dood.email 33 | assert @dood.valid? 34 | end 35 | 36 | def test_multiple_calls 37 | @dood.name = "tobi" 38 | assert !@dood.valid? 39 | 40 | @dood.email = "tobi@neech.de" 41 | assert !@dood.valid? 42 | 43 | @dood.country = 'DE' 44 | assert @dood.valid? 45 | end 46 | 47 | def test_messages 48 | @dood.valid? 49 | assert_equal "cannot be empty", @dood.errors.on('name') 50 | assert_equal "cannot be empty", @dood.errors.on('email') 51 | assert_equal nil, @dood.errors.on('doesnt_exist') 52 | 53 | end 54 | 55 | def test_full_messages 56 | @dood.valid? 57 | assert_equal ["Email cannot be empty", "Name cannot be empty", "The country cannot be blank"], @dood.errors.full_messages.sort 58 | end 59 | 60 | end 61 | -------------------------------------------------------------------------------- /test/remote/gateways/remote_beanstream_interac_test.rb: -------------------------------------------------------------------------------- 1 | require File.dirname(__FILE__) + '/../../test_helper' 2 | 3 | class RemoteBeanstreamInteracTest < Test::Unit::TestCase 4 | 5 | def setup 6 | @gateway = BeanstreamInteracGateway.new(fixtures(:beanstream_interac)) 7 | 8 | @amount = 100 9 | 10 | @options = { 11 | :order_id => generate_unique_id, 12 | :billing_address => { 13 | :name => 'xiaobo zzz', 14 | :phone => '555-555-5555', 15 | :address1 => '1234 Levesque St.', 16 | :address2 => 'Apt B', 17 | :city => 'Montreal', 18 | :state => 'QC', 19 | :country => 'CA', 20 | :zip => 'H2C1X8' 21 | }, 22 | :email => 'xiaobozzz@example.com', 23 | :subtotal => 800, 24 | :shipping => 100, 25 | :tax1 => 100, 26 | :tax2 => 100, 27 | :custom => 'reference one' 28 | } 29 | end 30 | 31 | def test_successful_purchase 32 | assert response = @gateway.purchase(@amount, @options) 33 | assert_success response 34 | assert_equal "R", response.params["responseType"] 35 | assert_false response.redirect.blank? 36 | end 37 | 38 | def test_failed_confirmation 39 | assert response = @gateway.confirm("") 40 | assert_failure response 41 | end 42 | 43 | def test_invalid_login 44 | gateway = BeanstreamInteracGateway.new( 45 | :merchant_id => '', 46 | :login => '', 47 | :password => '' 48 | ) 49 | assert response = gateway.purchase(@amount, @options) 50 | assert_failure response 51 | assert_equal 'Invalid merchant id (merchant_id = 0)', response.message 52 | end 53 | end 54 | -------------------------------------------------------------------------------- /test/remote/gateways/remote_usa_epay_test.rb: -------------------------------------------------------------------------------- 1 | require File.dirname(__FILE__) + '/../../test_helper' 2 | 3 | class RemoveUsaEpayTest < Test::Unit::TestCase 4 | def setup 5 | Base.gateway_mode = :test 6 | @gateway = UsaEpayGateway.new(fixtures(:usa_epay)) 7 | @creditcard = credit_card('4000100011112224') 8 | @declined_card = credit_card('4000300011112220') 9 | @options = { :billing_address => address } 10 | @amount = 100 11 | end 12 | 13 | def test_successful_purchase 14 | assert response = @gateway.purchase(@amount, @creditcard, @options) 15 | assert_equal 'Success', response.message 16 | assert_success response 17 | end 18 | 19 | def test_unsuccessful_purchase 20 | assert response = @gateway.purchase(@amount, @declined_card, @options) 21 | assert_equal 'Card Declined', response.message 22 | assert_failure response 23 | end 24 | 25 | def test_authorize_and_capture 26 | assert auth = @gateway.authorize(@amount, @creditcard, @options) 27 | assert_success auth 28 | assert_equal 'Success', auth.message 29 | assert auth.authorization 30 | assert capture = @gateway.capture(@amount, auth.authorization) 31 | assert_success capture 32 | end 33 | 34 | def test_failed_capture 35 | assert response = @gateway.capture(@amount, '') 36 | assert_failure response 37 | assert_equal 'Unable to find original transaciton.', response.message 38 | end 39 | 40 | def test_invalid_key 41 | gateway = UsaEpayGateway.new(:login => '') 42 | assert response = gateway.purchase(@amount, @creditcard, @options) 43 | assert_equal 'Specified source key not found.', response.message 44 | assert_failure response 45 | end 46 | end 47 | -------------------------------------------------------------------------------- /test/unit/gateways/gateway_test.rb: -------------------------------------------------------------------------------- 1 | require File.dirname(__FILE__) + '/../../test_helper' 2 | 3 | class GatewayTest < Test::Unit::TestCase 4 | def test_should_detect_if_a_card_is_supported 5 | Gateway.supported_cardtypes = [:visa, :bogus] 6 | assert [:visa, :bogus].all? { |supported_cardtype| Gateway.supports?(supported_cardtype) } 7 | 8 | Gateway.supported_cardtypes = [] 9 | assert_false [:visa, :bogus].all? { |invalid_cardtype| Gateway.supports?(invalid_cardtype) } 10 | end 11 | 12 | def test_should_gateway_uses_ssl_strict_checking_by_default 13 | assert Gateway.ssl_strict 14 | end 15 | 16 | def test_should_be_able_to_look_for_test_mode 17 | Base.gateway_mode = :test 18 | assert Gateway.new.test? 19 | 20 | Base.gateway_mode = :production 21 | assert_false Gateway.new.test? 22 | end 23 | 24 | def test_amount_style 25 | assert_equal '10.34', Gateway.new.send(:amount, 1034) 26 | 27 | assert_raise(ArgumentError) do 28 | Gateway.new.send(:amount, '10.34') 29 | end 30 | end 31 | 32 | def test_invalid_type 33 | credit_card = stub(:type => "visa") 34 | assert_equal "visa", Gateway.card_brand(credit_card) 35 | end 36 | 37 | def test_invalid_type 38 | credit_card = stub(:type => "String", :brand => "visa") 39 | assert_equal "visa", Gateway.card_brand(credit_card) 40 | end 41 | 42 | def test_setting_application_id_outside_the_class_definition 43 | assert_equal SimpleTestGateway.application_id, SubclassGateway.application_id 44 | SimpleTestGateway.application_id = "New Application ID" 45 | 46 | assert_equal SimpleTestGateway.application_id, SubclassGateway.application_id 47 | end 48 | end -------------------------------------------------------------------------------- /test/remote/gateways/remote_paypal_express_nv_test.rb: -------------------------------------------------------------------------------- 1 | require File.dirname(__FILE__) + '/../../test_helper' 2 | 3 | class PaypalExpressNvTest < Test::Unit::TestCase 4 | def setup 5 | Base.gateway_mode = :test 6 | 7 | @gateway = PaypalExpressNvGateway.new(fixtures(:paypal_signature)) 8 | 9 | @options = { 10 | :order_id => '230000', 11 | :email => 'buyer@jadedpallet.com', 12 | :billing_address => { :name => 'Fred Brooks', 13 | :address1 => '1234 Penny Lane', 14 | :city => 'Jonsetown', 15 | :state => 'NC', 16 | :country => 'US', 17 | :zip => '23456' 18 | } , 19 | :description => 'Stuff that you purchased, yo!', 20 | :ip => '10.0.0.1', 21 | :return_url => 'http://example.com/return', 22 | :cancel_return_url => 'http://example.com/cancel' 23 | } 24 | end 25 | 26 | def test_set_express_authorization 27 | @options.update( 28 | :return_url => 'http://example.com', 29 | :cancel_return_url => 'http://example.com', 30 | :email => 'Buyer1@paypal.com' 31 | ) 32 | response = @gateway.setup_authorization(500, @options) 33 | assert response.success? 34 | assert response.test? 35 | assert !response.params['token'].blank? 36 | end 37 | 38 | def test_set_express_purchase 39 | @options.update( 40 | :return_url => 'http://example.com', 41 | :cancel_return_url => 'http://example.com', 42 | :email => 'Buyer1@paypal.com' 43 | ) 44 | response = @gateway.setup_purchase(500, @options) 45 | assert response.success? 46 | assert response.test? 47 | assert !response.params['token'].blank? 48 | end 49 | 50 | end 51 | -------------------------------------------------------------------------------- /test/remote/gateways/remote_paypal_express_test.rb: -------------------------------------------------------------------------------- 1 | require File.dirname(__FILE__) + '/../../test_helper' 2 | 3 | class PaypalExpressTest < Test::Unit::TestCase 4 | def setup 5 | Base.gateway_mode = :test 6 | 7 | @gateway = PaypalExpressGateway.new(fixtures(:paypal_certificate)) 8 | 9 | @options = { 10 | :order_id => '230000', 11 | :email => 'buyer@jadedpallet.com', 12 | :billing_address => { :name => 'Fred Brooks', 13 | :address1 => '1234 Penny Lane', 14 | :city => 'Jonsetown', 15 | :state => 'NC', 16 | :country => 'US', 17 | :zip => '23456' 18 | } , 19 | :description => 'Stuff that you purchased, yo!', 20 | :ip => '10.0.0.1', 21 | :return_url => 'http://example.com/return', 22 | :cancel_return_url => 'http://example.com/cancel' 23 | } 24 | end 25 | 26 | def test_set_express_authorization 27 | @options.update( 28 | :return_url => 'http://example.com', 29 | :cancel_return_url => 'http://example.com', 30 | :email => 'Buyer1@paypal.com' 31 | ) 32 | response = @gateway.setup_authorization(500, @options) 33 | assert response.success? 34 | assert response.test? 35 | assert !response.params['token'].blank? 36 | end 37 | 38 | def test_set_express_purchase 39 | @options.update( 40 | :return_url => 'http://example.com', 41 | :cancel_return_url => 'http://example.com', 42 | :email => 'Buyer1@paypal.com' 43 | ) 44 | response = @gateway.setup_purchase(500, @options) 45 | assert response.success? 46 | assert response.test? 47 | assert !response.params['token'].blank? 48 | end 49 | end 50 | -------------------------------------------------------------------------------- /test/remote/gateways/remote_psigate_test.rb: -------------------------------------------------------------------------------- 1 | require File.dirname(__FILE__) + '/../../test_helper' 2 | 3 | class PsigateRemoteTest < Test::Unit::TestCase 4 | 5 | def setup 6 | Base.mode = :test 7 | @gateway = PsigateGateway.new(fixtures(:psigate)) 8 | 9 | @amount = 2400 10 | @creditcard = credit_card('4242424242424242') 11 | @options = { 12 | :order_id => generate_unique_id, 13 | :billing_address => address, 14 | :email => 'jack@example.com' 15 | } 16 | end 17 | 18 | def test_successful_authorization 19 | assert response = @gateway.authorize(@amount, @creditcard, @options) 20 | assert_success response 21 | assert_equal @options[:order_id], response.authorization 22 | end 23 | 24 | def test_successful_purchase 25 | assert response = @gateway.purchase(@amount, @creditcard, @options) 26 | assert_success response 27 | assert_equal @options[:order_id], response.authorization 28 | end 29 | 30 | def test_successful_authorization_and_capture 31 | assert authorization = @gateway.authorize(@amount, @creditcard, @options) 32 | assert_success authorization 33 | 34 | assert capture = @gateway.capture(@amount, authorization.authorization) 35 | assert_success capture 36 | end 37 | 38 | def test_successful_purchase_and_credit 39 | assert purchase = @gateway.purchase(@amount, @creditcard, @options) 40 | assert_success purchase 41 | 42 | assert credit = @gateway.credit(@amount, purchase.authorization) 43 | assert_success credit 44 | end 45 | 46 | def test_failed_purchase 47 | assert response = @gateway.purchase(@amount, @creditcard, @options.update(:test_result => 'D')) 48 | assert_failure response 49 | end 50 | end 51 | -------------------------------------------------------------------------------- /test/unit/integrations/notifications/nochex_notification_test.rb: -------------------------------------------------------------------------------- 1 | require File.dirname(__FILE__) + '/../../../test_helper' 2 | 3 | class NochexNotificationTest < Test::Unit::TestCase 4 | include ActiveMerchant::Billing::Integrations 5 | 6 | def setup 7 | @nochex = Nochex::Notification.new(http_raw_data) 8 | end 9 | 10 | def test_accessors 11 | assert @nochex.complete? 12 | assert_equal "Completed", @nochex.status 13 | assert_equal "91191", @nochex.transaction_id 14 | assert_equal "11", @nochex.item_id 15 | assert_equal "31.66", @nochex.gross 16 | assert_equal "GBP", @nochex.currency 17 | assert_equal Time.utc(2006, 9, 27, 22, 30, 53), @nochex.received_at 18 | assert @nochex.test? 19 | end 20 | 21 | def test_compositions 22 | assert_equal Money.new(3166, 'GBP'), @nochex.amount 23 | end 24 | 25 | def test_successful_acknowledgement 26 | Nochex::Notification.any_instance.expects(:ssl_post).returns('AUTHORISED') 27 | 28 | assert @nochex.acknowledge 29 | end 30 | 31 | def test_failed_acknowledgement 32 | Nochex::Notification.any_instance.expects(:ssl_post).returns('DECLINED') 33 | 34 | assert !@nochex.acknowledge 35 | end 36 | 37 | def test_respond_to_acknowledge 38 | assert @nochex.respond_to?(:acknowledge) 39 | end 40 | 41 | def test_nil_notification 42 | Nochex::Notification.any_instance.expects(:ssl_post).returns('DECLINED') 43 | notification = Nochex::Notification.new(nil) 44 | assert !notification.acknowledge 45 | end 46 | 47 | private 48 | def http_raw_data 49 | "transaction_date=27/09/2006 22:30:53&transaction_id=91191&order_id=11&from_email=test2@nochex.com&to_email=test1@nochex.com&amount=31.66&security_key=L254524366479818252491366&status=test&custom=" 50 | end 51 | end 52 | -------------------------------------------------------------------------------- /generators/integration/templates/helper_test.rb: -------------------------------------------------------------------------------- 1 | require File.dirname(__FILE__) + '/../../../test_helper' 2 | 3 | class <%= class_name %>HelperTest < Test::Unit::TestCase 4 | include ActiveMerchant::Billing::Integrations 5 | 6 | def setup 7 | @helper = <%= class_name %>::Helper.new('order-500','cody@example.com', :amount => 500, :currency => 'USD') 8 | end 9 | 10 | def test_basic_helper_fields 11 | assert_field '', 'cody@example.com' 12 | 13 | assert_field '', '5.00' 14 | assert_field '', 'order-500' 15 | end 16 | 17 | def test_customer_fields 18 | @helper.customer :first_name => 'Cody', :last_name => 'Fauser', :email => 'cody@example.com' 19 | assert_field '', 'Cody' 20 | assert_field '', 'Fauser' 21 | assert_field '', 'cody@example.com' 22 | end 23 | 24 | def test_address_mapping 25 | @helper.billing_address :address1 => '1 My Street', 26 | :address2 => '', 27 | :city => 'Leeds', 28 | :state => 'Yorkshire', 29 | :zip => 'LS2 7EE', 30 | :country => 'CA' 31 | 32 | assert_field '', '1 My Street' 33 | assert_field '', 'Leeds' 34 | assert_field '', 'Yorkshire' 35 | assert_field '', 'LS2 7EE' 36 | end 37 | 38 | def test_unknown_address_mapping 39 | @helper.billing_address :farm => 'CA' 40 | assert_equal 3, @helper.fields.size 41 | end 42 | 43 | def test_unknown_mapping 44 | assert_nothing_raised do 45 | @helper.company_address :address => '500 Dwemthy Fox Road' 46 | end 47 | end 48 | 49 | def test_setting_invalid_address_field 50 | fields = @helper.fields.dup 51 | @helper.billing_address :street => 'My Street' 52 | assert_equal fields, @helper.fields 53 | end 54 | end 55 | -------------------------------------------------------------------------------- /test/unit/integrations/helpers/nochex_helper_test.rb: -------------------------------------------------------------------------------- 1 | require File.dirname(__FILE__) + '/../../../test_helper' 2 | 3 | class NochexHelperTest < Test::Unit::TestCase 4 | include ActiveMerchant::Billing::Integrations 5 | 6 | def setup 7 | @helper = Nochex::Helper.new('order-500','cody@example.com', :amount => 500, :currency => 'GBP') 8 | end 9 | 10 | def test_basic_helper_fields 11 | assert_field 'email', 'cody@example.com' 12 | 13 | # Nochex requires 2 decimal places on the amount 14 | assert_field 'amount', '5.00' 15 | assert_field 'ordernumber', 'order-500' 16 | end 17 | 18 | def test_customer_fields 19 | @helper.customer :first_name => 'Cody', :last_name => 'Fauser', :email => 'cody@example.com' 20 | assert_field 'firstname', 'Cody' 21 | assert_field 'lastname', 'Fauser' 22 | assert_field 'email_address_sender', 'cody@example.com' 23 | end 24 | 25 | def test_address_mapping 26 | @helper.billing_address :address1 => '1 My Street', 27 | :city => 'Leeds', 28 | :state => 'Yorkshire', 29 | :zip => 'LS2 7EE' 30 | 31 | assert_field 'firstline', '1 My Street' 32 | assert_field 'town', 'Leeds' 33 | assert_field 'county', 'Yorkshire' 34 | assert_field 'postcode', 'LS2 7EE' 35 | end 36 | 37 | def test_unknown_address_mapping 38 | @helper.billing_address :country => 'CA' 39 | assert_equal 3, @helper.fields.size 40 | end 41 | 42 | def test_unknown_mapping 43 | assert_nothing_raised do 44 | @helper.company_address :address => '500 Dwemthy Fox Road' 45 | end 46 | end 47 | 48 | def test_setting_invalid_address_field 49 | fields = @helper.fields.dup 50 | @helper.billing_address :street => 'My Street' 51 | assert_equal fields, @helper.fields 52 | end 53 | end 54 | -------------------------------------------------------------------------------- /test/unit/avs_result_test.rb: -------------------------------------------------------------------------------- 1 | require File.dirname(__FILE__) + '/../test_helper' 2 | 3 | class AVSResultTest < Test::Unit::TestCase 4 | def test_nil 5 | result = AVSResult.new(nil) 6 | end 7 | 8 | def test_no_match 9 | result = AVSResult.new(:code => 'N') 10 | assert_equal 'N', result.code 11 | assert_equal 'N', result.street_match 12 | assert_equal 'N', result.postal_match 13 | assert_equal AVSResult.messages['N'], result.message 14 | end 15 | 16 | def test_only_street_match 17 | result = AVSResult.new(:code => 'A') 18 | assert_equal 'A', result.code 19 | assert_equal 'Y', result.street_match 20 | assert_equal 'N', result.postal_match 21 | assert_equal AVSResult.messages['A'], result.message 22 | end 23 | 24 | def test_only_postal_match 25 | result = AVSResult.new(:code => 'W') 26 | assert_equal 'W', result.code 27 | assert_equal 'N', result.street_match 28 | assert_equal 'Y', result.postal_match 29 | assert_equal AVSResult.messages['W'], result.message 30 | end 31 | 32 | def test_nil_data 33 | result = AVSResult.new(:code => nil) 34 | assert_nil result.code 35 | assert_nil result.message 36 | end 37 | 38 | def test_empty_data 39 | result = AVSResult.new(:code => '') 40 | assert_nil result.code 41 | assert_nil result.message 42 | end 43 | 44 | def test_to_hash 45 | avs_data = AVSResult.new(:code => 'X').to_hash 46 | assert_equal 'X', avs_data['code'] 47 | assert_equal AVSResult.messages['X'], avs_data['message'] 48 | end 49 | 50 | def test_street_match 51 | avs_data = AVSResult.new(:street_match => 'Y') 52 | assert_equal 'Y', avs_data.street_match 53 | end 54 | 55 | def test_postal_match 56 | avs_data = AVSResult.new(:postal_match => 'Y') 57 | assert_equal 'Y', avs_data.postal_match 58 | end 59 | end -------------------------------------------------------------------------------- /lib/active_merchant/billing/gateways/beanstream_interac.rb: -------------------------------------------------------------------------------- 1 | require File.dirname(__FILE__) + '/beanstream/beanstream_core' 2 | 3 | module ActiveMerchant #:nodoc: 4 | module Billing #:nodoc: 5 | class BeanstreamInteracResponse < Response 6 | def redirect 7 | params['pageContents'] 8 | end 9 | end 10 | 11 | class BeanstreamInteracGateway < Gateway 12 | include BeanstreamCore 13 | 14 | # Confirm a transaction posted back from the bank to Beanstream. 15 | # Confirming a transaction does not require any credentials, 16 | # and in an application with many merchants sharing a funded 17 | # URL the application may not yet know which merchant the 18 | # post back is for until the response of the confirmation is 19 | # received, which contains the order number. 20 | def self.confirm(transaction) 21 | gateway = new(:login => '') 22 | gateway.confirm(transaction) 23 | end 24 | 25 | def purchase(money, options = {}) 26 | post = {} 27 | add_amount(post, money) 28 | add_invoice(post, options) 29 | add_address(post, options) 30 | add_interac_details(post, options) 31 | add_transaction_type(post, :purchase) 32 | commit(post) 33 | end 34 | 35 | # Confirm a transaction posted back from the bank to Beanstream. 36 | def confirm(transaction) 37 | post(transaction) 38 | end 39 | 40 | private 41 | 42 | def add_interac_details(post, options) 43 | address = options[:billing_address] || options[:address] || {} 44 | post[:trnCardOwner] = address[:name] 45 | post[:paymentMethod] = 'IO' 46 | end 47 | 48 | def build_response(*args) 49 | BeanstreamInteracResponse.new(*args) 50 | end 51 | end 52 | end 53 | end 54 | 55 | -------------------------------------------------------------------------------- /test/unit/generators/test_gateway_generator.rb: -------------------------------------------------------------------------------- 1 | require File.join(File.dirname(__FILE__), "test_generator_helper.rb") 2 | 3 | class TestGatewayGenerator < Test::Unit::TestCase 4 | include RubiGen::GeneratorTestHelper 5 | 6 | def setup 7 | bare_setup 8 | end 9 | 10 | def teardown 11 | bare_teardown 12 | end 13 | 14 | # Some generator-related assertions: 15 | # assert_generated_file(name, &block) # block passed the file contents 16 | # assert_directory_exists(name) 17 | # assert_generated_class(name, &block) 18 | # assert_generated_module(name, &block) 19 | # assert_generated_test_for(name, &block) 20 | # The assert_generated_(class|module|test_for) &block is passed the body of the class/module within the file 21 | # assert_has_method(body, *methods) # check that the body has a list of methods (methods with parentheses not supported yet) 22 | # 23 | # Other helper methods are: 24 | # app_root_files - put this in teardown to show files generated by the test method (e.g. p app_root_files) 25 | # bare_setup - place this in setup method to create the APP_ROOT folder for each test 26 | # bare_teardown - place this in teardown method to destroy the TMP_ROOT or APP_ROOT folder after each test 27 | 28 | def test_generator_without_options 29 | name = 'miracle' 30 | 31 | run_generator('gateway', [ name ], sources) 32 | assert_generated_file(GatewayGenerator::LIB_DIR + "#{name}.rb") 33 | assert_generated_file(GatewayGenerator::UNIT_TEST_DIR + "#{name}_test.rb") 34 | assert_generated_file(GatewayGenerator::REMOTE_TEST_DIR + "remote_#{name}_test.rb") 35 | end 36 | 37 | private 38 | def sources 39 | [RubiGen::PathSource.new(:test, File.join(File.dirname(__FILE__),"..", generator_path)) 40 | ] 41 | end 42 | 43 | def generator_path 44 | "generators" 45 | end 46 | end 47 | -------------------------------------------------------------------------------- /generators/gateway/gateway_generator.rb: -------------------------------------------------------------------------------- 1 | class GatewayGenerator < RubiGen::Base 2 | LIB_DIR = "lib/active_merchant/billing/gateways/" 3 | UNIT_TEST_DIR = "test/unit/gateways/" 4 | REMOTE_TEST_DIR = "test/remote/gateways/" 5 | 6 | 7 | default_options :author => nil 8 | 9 | attr_reader :name 10 | 11 | def initialize(runtime_args, runtime_options = {}) 12 | super 13 | usage if args.length < 1 14 | @name = args.shift 15 | extract_options 16 | end 17 | 18 | def class_name 19 | @name.classify 20 | end 21 | 22 | def manifest 23 | record do |m| 24 | 25 | m.directory LIB_DIR 26 | m.directory UNIT_TEST_DIR 27 | m.directory REMOTE_TEST_DIR 28 | 29 | m.template 'gateway.rb', LIB_DIR + "#{name}.rb" 30 | m.template 'gateway_test.rb', UNIT_TEST_DIR + "#{name}_test.rb" 31 | m.template 'remote_gateway_test.rb', REMOTE_TEST_DIR + "remote_#{name}_test.rb" 32 | end 33 | end 34 | 35 | protected 36 | def banner 37 | <<-EOS 38 | Creates a ... 39 | 40 | USAGE: #{$0} #{spec.name} name" 41 | EOS 42 | end 43 | 44 | def add_options!(opts) 45 | # opts.separator '' 46 | # opts.separator 'Options:' 47 | # For each option below, place the default 48 | # at the top of the file next to "default_options" 49 | # opts.on("-a", "--author=\"Your Name\"", String, 50 | # "Some comment about this option", 51 | # "Default: none") { |options[:author]| } 52 | # opts.on("-v", "--version", "Show the #{File.basename($0)} version number and quit.") 53 | end 54 | 55 | def extract_options 56 | # for each option, extract it into a local variable (and create an "attr_reader :author" at the top) 57 | # Templates can access these value via the attr_reader-generated methods, but not the 58 | # raw instance variable value. 59 | # @author = options[:author] 60 | end 61 | end -------------------------------------------------------------------------------- /lib/active_merchant/lib/validateable.rb: -------------------------------------------------------------------------------- 1 | module ActiveMerchant #:nodoc: 2 | module Validateable #:nodoc: 3 | def valid? 4 | errors.clear 5 | 6 | before_validate if respond_to?(:before_validate, true) 7 | validate if respond_to?(:validate, true) 8 | 9 | errors.empty? 10 | end 11 | 12 | def initialize(attributes = {}) 13 | self.attributes = attributes 14 | end 15 | 16 | def errors 17 | @errors ||= Errors.new(self) 18 | end 19 | 20 | private 21 | 22 | def attributes=(attributes) 23 | unless attributes.nil? 24 | for key, value in attributes 25 | send("#{key}=", value ) 26 | end 27 | end 28 | end 29 | 30 | # This hash keeps the errors of the object 31 | class Errors < HashWithIndifferentAccess 32 | 33 | def initialize(base) 34 | @base = base 35 | end 36 | 37 | def count 38 | size 39 | end 40 | 41 | # returns a specific fields error message. 42 | # if more than one error is available we will only return the first. If no error is available 43 | # we return an empty string 44 | def on(field) 45 | self[field].to_a.first 46 | end 47 | 48 | def add(field, error) 49 | self[field] ||= [] 50 | self[field] << error 51 | end 52 | 53 | def add_to_base(error) 54 | add(:base, error) 55 | end 56 | 57 | def each_full 58 | full_messages.each { |msg| yield msg } 59 | end 60 | 61 | def full_messages 62 | result = [] 63 | 64 | self.each do |key, messages| 65 | if key == 'base' 66 | result << "#{messages.first}" 67 | else 68 | result << "#{key.to_s.humanize} #{messages.first}" 69 | end 70 | end 71 | 72 | result 73 | end 74 | end 75 | end 76 | end -------------------------------------------------------------------------------- /test/unit/gateways/netbilling_test.rb: -------------------------------------------------------------------------------- 1 | require File.dirname(__FILE__) + '/../../test_helper' 2 | 3 | class NetbillingTest < Test::Unit::TestCase 4 | def setup 5 | @gateway = NetbillingGateway.new( 6 | :login => 'login', 7 | :password => 'password' 8 | ) 9 | 10 | @credit_card = credit_card('4242424242424242') 11 | @amount = 100 12 | @options = { :billing_address => address } 13 | end 14 | 15 | def test_successful_request 16 | @gateway.expects(:ssl_post).returns(successful_purchase_response) 17 | 18 | assert response = @gateway.purchase(@amount, @credit_card, @options) 19 | assert_success response 20 | assert_equal '110270311543', response.authorization 21 | assert response.test? 22 | end 23 | 24 | def test_unsuccessful_request 25 | @gateway.expects(:ssl_post).returns(unsuccessful_purchase_response) 26 | 27 | assert response = @gateway.purchase(@amount, @credit_card, @options) 28 | assert_failure response 29 | assert response.test? 30 | end 31 | 32 | def test_avs_result 33 | @gateway.expects(:ssl_post).returns(successful_purchase_response) 34 | 35 | response = @gateway.purchase(@amount, @credit_card, @options) 36 | assert_equal 'X', response.avs_result['code'] 37 | end 38 | 39 | def test_cvv_result 40 | @gateway.expects(:ssl_post).returns(successful_purchase_response) 41 | 42 | response = @gateway.purchase(@amount, @credit_card, @options) 43 | assert_equal 'M', response.cvv_result['code'] 44 | end 45 | 46 | private 47 | def successful_purchase_response 48 | "avs_code=X&cvv2_code=M&status_code=1&auth_code=999999&trans_id=110270311543&auth_msg=TEST+APPROVED&auth_date=2008-01-25+16:43:54" 49 | end 50 | 51 | def unsuccessful_purchase_response 52 | "status_code=0&auth_msg=CARD+EXPIRED&trans_id=110492608613&auth_date=2008-01-25+17:47:44" 53 | end 54 | end 55 | -------------------------------------------------------------------------------- /test/unit/base_test.rb: -------------------------------------------------------------------------------- 1 | require File.dirname(__FILE__) + '/../test_helper' 2 | 3 | class BaseTest < Test::Unit::TestCase 4 | def setup 5 | ActiveMerchant::Billing::Base.mode = :test 6 | end 7 | 8 | def teardown 9 | ActiveMerchant::Billing::Base.mode = :test 10 | end 11 | 12 | def test_should_return_a_new_gateway_specified_by_symbol_name 13 | assert_equal BogusGateway, Base.gateway(:bogus) 14 | assert_equal MonerisGateway, Base.gateway(:moneris) 15 | assert_equal AuthorizeNetGateway, Base.gateway(:authorize_net) 16 | assert_equal UsaEpayGateway, Base.gateway(:usa_epay) 17 | assert_equal LinkpointGateway, Base.gateway(:linkpoint) 18 | assert_equal AuthorizedNetGateway, Base.gateway(:authorized_net) 19 | end 20 | 21 | def test_should_return_an_integration_by_name 22 | chronopay = Base.integration(:chronopay) 23 | 24 | assert_equal Integrations::Chronopay, chronopay 25 | assert_instance_of Integrations::Chronopay::Notification, chronopay.notification('name=cody') 26 | end 27 | 28 | def test_should_set_modes 29 | Base.mode = :test 30 | assert_equal :test, Base.mode 31 | assert_equal :test, Base.gateway_mode 32 | assert_equal :test, Base.integration_mode 33 | 34 | Base.mode = :production 35 | assert_equal :production, Base.mode 36 | assert_equal :production, Base.gateway_mode 37 | assert_equal :production, Base.integration_mode 38 | 39 | Base.mode = :development 40 | Base.gateway_mode = :test 41 | Base.integration_mode = :staging 42 | assert_equal :development, Base.mode 43 | assert_equal :test, Base.gateway_mode 44 | assert_equal :staging, Base.integration_mode 45 | end 46 | 47 | def test_should_identify_if_test_mode 48 | Base.gateway_mode = :test 49 | assert Base.test? 50 | 51 | Base.gateway_mode = :production 52 | assert_false Base.test? 53 | end 54 | 55 | end 56 | -------------------------------------------------------------------------------- /test/remote/gateways/remote_sage_virtual_check_test.rb: -------------------------------------------------------------------------------- 1 | require File.dirname(__FILE__) + '/../../test_helper' 2 | 3 | class RemoteSageCheckTest < Test::Unit::TestCase 4 | 5 | def setup 6 | @gateway = SageVirtualCheckGateway.new(fixtures(:sage)) 7 | 8 | @amount = 100 9 | @check = check 10 | 11 | @options = { 12 | :order_id => generate_unique_id, 13 | :billing_address => address, 14 | :shipping_address => address, 15 | :email => 'longbob@example.com', 16 | :drivers_license_state => 'CA', 17 | :drivers_license_number => '12345689', 18 | :date_of_birth => Date.new(1978, 8, 11), 19 | :ssn => '078051120' 20 | } 21 | end 22 | 23 | def test_successful_check_purchase 24 | assert response = @gateway.purchase(@amount, @check, @options) 25 | assert_success response 26 | assert response.test? 27 | assert_false response.authorization.blank? 28 | end 29 | 30 | def test_failed_check_purchase 31 | @check.routing_number = "" 32 | 33 | assert response = @gateway.purchase(@amount, @check, @options) 34 | assert_failure response 35 | assert response.test? 36 | assert_false response.authorization.blank? 37 | end 38 | 39 | def test_purchase_and_void 40 | assert purchase = @gateway.purchase(@amount, @check, @options) 41 | assert_success purchase 42 | 43 | assert void = @gateway.void(purchase.authorization) 44 | assert_success void 45 | end 46 | 47 | def test_credit 48 | assert response = @gateway.credit(@amount, @check, @options) 49 | assert_success response 50 | assert response.test? 51 | end 52 | 53 | def test_invalid_login 54 | gateway = SageVirtualCheckGateway.new( 55 | :login => '', 56 | :password => '' 57 | ) 58 | assert response = gateway.purchase(@amount, @check, @options) 59 | assert_failure response 60 | assert_equal 'SECURITY VIOLATION', response.message 61 | end 62 | end 63 | -------------------------------------------------------------------------------- /generators/gateway/templates/remote_gateway_test.rb: -------------------------------------------------------------------------------- 1 | require File.dirname(__FILE__) + '/../test_helper' 2 | 3 | class Remote<%= class_name %>Test < Test::Unit::TestCase 4 | 5 | 6 | def setup 7 | @gateway = <%= class_name %>Gateway.new(fixtures(:<%= class_name.underscore %>)) 8 | 9 | @amount = 100 10 | @credit_card = credit_card('4000100011112224') 11 | @declined_card = credit_card('4000300011112220') 12 | 13 | @options = { 14 | :order_id => '1', 15 | :billing_address => address, 16 | :description => 'Store Purchase' 17 | } 18 | end 19 | 20 | def test_successful_purchase 21 | assert response = @gateway.purchase(@amount, @credit_card, @options) 22 | assert_success response 23 | assert_equal 'REPLACE WITH SUCCESS MESSAGE', response.message 24 | end 25 | 26 | def test_unsuccessful_purchase 27 | assert response = @gateway.purchase(@amount, @declined_card, @options) 28 | assert_failure response 29 | assert_equal 'REPLACE WITH FAILED PURCHASE MESSAGE', response.message 30 | end 31 | 32 | def test_authorize_and_capture 33 | amount = @amount 34 | assert auth = @gateway.authorize(amount, @credit_card, @options) 35 | assert_success auth 36 | assert_equal 'Success', auth.message 37 | assert auth.authorization 38 | assert capture = @gateway.capture(amount, auth.authorization) 39 | assert_success capture 40 | end 41 | 42 | def test_failed_capture 43 | assert response = @gateway.capture(@amount, '') 44 | assert_failure response 45 | assert_equal 'REPLACE WITH GATEWAY FAILURE MESSAGE', response.message 46 | end 47 | 48 | def test_invalid_login 49 | gateway = <%= class_name %>Gateway.new( 50 | :login => '', 51 | :password => '' 52 | ) 53 | assert response = gateway.purchase(@amount, @credit_card, @options) 54 | assert_failure response 55 | assert_equal 'REPLACE WITH FAILURE MESSAGE', response.message 56 | end 57 | end 58 | -------------------------------------------------------------------------------- /test/remote/gateways/remote_payflow_express_test.rb: -------------------------------------------------------------------------------- 1 | require File.dirname(__FILE__) + '/../../test_helper' 2 | 3 | class RemotePayflowTest < Test::Unit::TestCase 4 | def setup 5 | Base.gateway_mode = :test 6 | 7 | @gateway = PayflowExpressGateway.new(fixtures(:payflow)) 8 | 9 | @options = { :billing_address => { 10 | :name => 'Cody Fauser', 11 | :address1 => '1234 Shady Brook Lane', 12 | :city => 'Ottawa', 13 | :state => 'ON', 14 | :country => 'CA', 15 | :zip => '90210', 16 | :phone => '555-555-5555' 17 | }, 18 | :email => 'cody@example.com' 19 | } 20 | end 21 | 22 | # Only works with a Payflow 2.0 account or by requesting the addition 23 | # of Express checkout to an existing Payflow Pro account. This can be done 24 | # by contacting Payflow sales. The PayPal account used must be a business 25 | # account and the Payflow Pro account must be in Live mode in order for 26 | # the tests to work correctly 27 | def test_set_express_authorization 28 | @options.update( 29 | :return_url => 'http://example.com', 30 | :cancel_return_url => 'http://example.com', 31 | :email => 'Buyer1@paypal.com' 32 | ) 33 | response = @gateway.setup_authorization(500, @options) 34 | assert response.success? 35 | assert response.test? 36 | assert !response.params['token'].blank? 37 | end 38 | 39 | def test_set_express_purchase 40 | @options.update( 41 | :return_url => 'http://example.com', 42 | :cancel_return_url => 'http://example.com', 43 | :email => 'Buyer1@paypal.com' 44 | ) 45 | response = @gateway.setup_purchase(500, @options) 46 | assert response.success? 47 | assert response.test? 48 | assert !response.params['token'].blank? 49 | end 50 | end 51 | -------------------------------------------------------------------------------- /test/unit/country_test.rb: -------------------------------------------------------------------------------- 1 | require File.dirname(__FILE__) + '/../test_helper' 2 | 3 | class CountryTest < Test::Unit::TestCase 4 | include ActiveMerchant 5 | 6 | def test_country_from_hash 7 | country = Country.new(:name => 'Canada', :alpha2 => 'CA', :alpha3 => 'CAN', :numeric => '124') 8 | assert_equal 'CA', country.code(:alpha2).to_s 9 | assert_equal 'CAN', country.code(:alpha3).to_s 10 | assert_equal '124', country.code(:numeric).to_s 11 | assert_equal 'Canada', country.to_s 12 | end 13 | 14 | def test_country_for_alpha2_code 15 | country = Country.find('CA') 16 | assert_equal 'CA', country.code(:alpha2).to_s 17 | assert_equal 'CAN', country.code(:alpha3).to_s 18 | assert_equal '124', country.code(:numeric).to_s 19 | assert_equal 'Canada', country.to_s 20 | end 21 | 22 | def test_country_for_alpha3_code 23 | country = Country.find('CAN') 24 | assert_equal 'Canada', country.to_s 25 | end 26 | 27 | def test_country_for_numeric_code 28 | country = Country.find('124') 29 | assert_equal 'Canada', country.to_s 30 | end 31 | 32 | def test_find_country_by_name 33 | country = Country.find('Canada') 34 | assert_equal 'Canada', country.to_s 35 | end 36 | 37 | def test_find_unknown_country_name 38 | assert_raise(InvalidCountryCodeError) do 39 | Country.find('Asskickistan') 40 | end 41 | end 42 | 43 | def test_find_australia 44 | country = Country.find('AU') 45 | assert_equal 'AU', country.code(:alpha2).to_s 46 | 47 | country = Country.find('Australia') 48 | assert_equal 'AU', country.code(:alpha2).to_s 49 | end 50 | 51 | def test_find_united_kingdom 52 | country = Country.find('GB') 53 | assert_equal 'GB', country.code(:alpha2).to_s 54 | 55 | country = Country.find('United Kingdom') 56 | assert_equal 'GB', country.code(:alpha2).to_s 57 | end 58 | 59 | def test_raise_on_nil_name 60 | assert_raise(InvalidCountryCodeError) do 61 | Country.find(nil) 62 | end 63 | end 64 | end 65 | -------------------------------------------------------------------------------- /lib/active_merchant/billing/integrations/hi_trust/helper.rb: -------------------------------------------------------------------------------- 1 | module ActiveMerchant #:nodoc: 2 | module Billing #:nodoc: 3 | module Integrations #:nodoc: 4 | module HiTrust 5 | class Helper < ActiveMerchant::Billing::Integrations::Helper 6 | 7 | # Transaction types 8 | # * Auth 9 | # * AuthRe 10 | # * Capture 11 | # * CaptureRe 12 | # * Refund 13 | # * RefundRe 14 | # * Query 15 | def initialize(order, account, options = {}) 16 | super 17 | # Perform an authorization by default 18 | add_field('Type', 'Auth') 19 | 20 | # Capture the payment right away 21 | add_field('depositflag', '1') 22 | 23 | # Disable auto query - who knows what it does? 24 | add_field('queryflag', '1') 25 | 26 | add_field('orderdesc', 'Store purchase') 27 | end 28 | 29 | mapping :account, 'storeid' 30 | mapping :amount, 'amount' 31 | 32 | def amount=(money) 33 | cents = money.respond_to?(:cents) ? money.cents : money 34 | 35 | if money.is_a?(String) or cents.to_i < 0 36 | raise ArgumentError, 'money amount must be either a Money object or a positive integer in cents.' 37 | end 38 | 39 | add_field(mappings[:amount], cents) 40 | end 41 | # Supported currencies include: 42 | # * CNY:Chinese Yuan (Renminbi) 43 | # * TWD:New Taiwan Dollar 44 | # * HKD:Hong Kong Dollar 45 | # * USD:US Dollar 46 | # * AUD:Austrian Dollar 47 | mapping :currency, 'currency' 48 | 49 | mapping :order, 'ordernumber' 50 | mapping :description, 'orderdesc' 51 | 52 | mapping :notify_url, 'merUpdateURL' 53 | mapping :return_url, 'returnURL' 54 | end 55 | end 56 | end 57 | end 58 | end -------------------------------------------------------------------------------- /test/remote/gateways/remote_modern_payments_cim_test.rb: -------------------------------------------------------------------------------- 1 | require File.dirname(__FILE__) + '/../../test_helper' 2 | 3 | class RemoteModernPaymentsCimTest < Test::Unit::TestCase 4 | 5 | 6 | def setup 7 | @gateway = ModernPaymentsCimGateway.new(fixtures(:modern_payments)) 8 | 9 | @amount = 100 10 | @credit_card = credit_card('4111111111111111') 11 | @declined_card = credit_card('4000000000000000') 12 | 13 | @options = { 14 | :billing_address => address, 15 | :customer => 'JIMSMITH2000' 16 | } 17 | end 18 | 19 | def test_successful_create_customer 20 | response = @gateway.create_customer(@options) 21 | assert_success response 22 | assert !response.params["create_customer_result"].blank? 23 | end 24 | 25 | def test_successful_modify_customer_credit_card 26 | customer = @gateway.create_customer(@options) 27 | assert_success customer 28 | 29 | customer_id = customer.params["create_customer_result"] 30 | 31 | credit_card = @gateway.modify_customer_credit_card(customer_id, @credit_card) 32 | assert_success credit_card 33 | assert !credit_card.params["modify_customer_credit_card_result"].blank? 34 | end 35 | 36 | def test_succsessful_authorize_credit_card_payment 37 | customer = @gateway.create_customer(@options) 38 | assert_success customer 39 | 40 | customer_id = customer.params["create_customer_result"] 41 | 42 | credit_card = @gateway.modify_customer_credit_card(customer_id, @credit_card) 43 | assert_success credit_card 44 | 45 | payment = @gateway.authorize_credit_card_payment(customer_id, @amount) 46 | assert_success payment 47 | end 48 | 49 | def test_invalid_login 50 | gateway = ModernPaymentsCimGateway.new( 51 | :login => '', 52 | :password => '' 53 | ) 54 | assert response = gateway.create_customer(@options) 55 | assert_failure response 56 | assert_equal ModernPaymentsCimGateway::ERROR_MESSAGE, response.message 57 | end 58 | end 59 | -------------------------------------------------------------------------------- /CONTRIBUTERS: -------------------------------------------------------------------------------- 1 | Protx Gateway 2 | 3 | * Contributed by shiftx (Vincent) 4 | 5 | Verifi Gateway 6 | 7 | * Contributed by Paul Hepworth on 2007-05-12. 8 | * Portions of Verifi Gateway Copyright (c) 2007 Paul Hepworth 9 | 10 | Plug 'N Pay Gateway 11 | 12 | * Contributed by Ryan Norbauer 13 | 14 | PayJunction Gateway 15 | 16 | * Contributed by Matt Sanders 17 | 18 | E-xact Gateway 19 | 20 | * Contributed by James Edward Gray II 21 | 22 | Linkpoint Gateway 23 | 24 | * Portions of the LinkPoint Gateway by Ryan Heneise 25 | 26 | eWay Gateway 27 | 28 | * Originally contributed by Lucas Carlson (mailto:lucas@rufy.com) 29 | 30 | CardStream Gateway 31 | 32 | * Portions of the Cardstream gateway by Jonah Fox and Thomas Nichols 33 | 34 | CyberSource Gateway 35 | 36 | * Contributed by Matt Margolis (matt@mattmargolis.net) 37 | 38 | NetRegistry Gateway 39 | 40 | * Originally contributed by George Ogata (mailto: george.ogata@gmail.com) 41 | 42 | Viaklix Gateway (Sep 3, 2007) 43 | 44 | * Originally contributed by Sal Scotto 45 | 46 | Braintree Gateway (Sep 4, 2007) 47 | 48 | * Originally contributed by Michael J. Mangino 49 | * Portions of the BrainTree gateway by Jeremy Voorhis 50 | 51 | Concord Efsnet Gateway (Sep 7, 2007) 52 | 53 | * Originally contributed by snacktime 54 | 55 | SecurePayTech Gateway (Oct 23, 2007) 56 | 57 | * Originally contributed by Jasper Bryant-Greene 58 | 59 | SkipJack Gateway (Nov 29, 2007) 60 | 61 | * Originally contributed by Bill Bereza - http://atomicobject.com 62 | 63 | HiTRUST Gateway (Dec 10, 2007) 64 | 65 | * Jaded Pixel 66 | 67 | Payflow NV Gateway (Mar 03, 2008) 68 | 69 | * Greg Furmanek 70 | 71 | PaypalNVGateway (Apr 12, 2008) 72 | 73 | * Greg Furmanek 74 | 75 | Beanstream (May 13, 2008) 76 | 77 | * Created by xiaobozz ( xiaobozzz at gmail dot com ) 78 | 79 | Sage (June, 2008) 80 | 81 | * Cody 82 | 83 | Modern Payments (June 13, 2008) 84 | 85 | * Initial implementation by Jeremy Nicoll 86 | * Additional portions by Cody Fauser 87 | 88 | Wirecard Gateway (June 30, 2008) 89 | 90 | * Initial implementation by Soleone 91 | -------------------------------------------------------------------------------- /test/remote/gateways/remote_payflow_express_nv_test.rb: -------------------------------------------------------------------------------- 1 | require File.dirname(__FILE__) + '/../../test_helper' 2 | 3 | class RemotePayflowNvTest < Test::Unit::TestCase 4 | def setup 5 | Base.gateway_mode = :test 6 | 7 | @gateway = PayflowExpressNvGateway.new(fixtures(:payflow)) 8 | 9 | @options = { :billing_address => { 10 | :name => 'Cody Fauser', 11 | :address1 => '1234 Shady Brook Lane', 12 | :city => 'Ottawa', 13 | :state => 'ON', 14 | :country => 'CA', 15 | :zip => '90210', 16 | :phone => '555-555-5555' 17 | }, 18 | :email => 'cody@example.com' 19 | } 20 | end 21 | 22 | # Only works with a Payflow 2.0 account or by requesting the addition 23 | # of Express checkout to an existing Payflow Pro account. This can be done 24 | # by contacting Payflow sales. The PayPal account used must be a business 25 | # account and the Payflow Pro account must be in Live mode in order for 26 | # the tests to work correctly 27 | def test_set_express_authorization 28 | @options.update( 29 | :return_url => 'http://example.com', 30 | :cancel_return_url => 'http://example.com', 31 | :email => 'Buyer1@paypal.com' 32 | ) 33 | response = @gateway.setup_authorization(500, @options) 34 | puts response.inspect 35 | assert response.success?, response.message 36 | assert response.test? 37 | assert !response.params['token'].blank? 38 | end 39 | 40 | def test_set_express_purchase 41 | @options.update( 42 | :return_url => 'http://example.com', 43 | :cancel_return_url => 'http://example.com', 44 | :email => 'Buyer1@paypal.com' 45 | ) 46 | response = @gateway.setup_purchase(500, @options) 47 | assert response.success?, response.message 48 | assert response.test? 49 | assert !response.params['token'].blank? 50 | end 51 | end 52 | -------------------------------------------------------------------------------- /test/unit/integrations/notifications/hi_trust_notification_test.rb: -------------------------------------------------------------------------------- 1 | require File.dirname(__FILE__) + '/../../../test_helper' 2 | 3 | class HiTrustNotificationTest < Test::Unit::TestCase 4 | include ActiveMerchant::Billing::Integrations 5 | 6 | def setup 7 | @notification = HiTrust::Notification.new(successful_response) 8 | end 9 | 10 | def teardown 11 | ActiveMerchant::Billing::Base.integration_mode = :test 12 | end 13 | 14 | def test_accessors 15 | assert @notification.complete? 16 | assert_equal "Completed", @notification.status 17 | assert_equal "012345678901", @notification.transaction_id 18 | assert_equal "1000", @notification.item_id 19 | assert_equal "101010", @notification.account 20 | assert_equal "5.00", @notification.gross 21 | assert_equal "USD", @notification.currency 22 | assert_equal Time.parse("2007-12-01.12.35.40.123456"), @notification.received_at 23 | assert @notification.test? 24 | end 25 | 26 | def test_compositions 27 | assert_equal Money.new(500, 'USD'), @notification.amount 28 | end 29 | 30 | def test_send_acknowledgement 31 | assert @notification.acknowledge 32 | end 33 | 34 | def test_respond_to_acknowledge 35 | assert @notification.respond_to?(:acknowledge) 36 | end 37 | 38 | def test_valid_sender_in_testmode_always_true 39 | assert @notification.test? 40 | assert @notification.valid_sender?('127.0.0.1') 41 | assert @notification.valid_sender?(nil) 42 | end 43 | 44 | def test_valid_sender 45 | ActiveMerchant::Billing::Base.integration_mode = :production 46 | assert @notification.valid_sender?('203.75.242.8') 47 | end 48 | 49 | def test_invalid_sender 50 | ActiveMerchant::Billing::Base.integration_mode = :production 51 | assert_false @notification.valid_sender?('127.0.0.1') 52 | assert_false @notification.valid_sender?(nil) 53 | end 54 | 55 | private 56 | def successful_response 57 | 'retcode=00&ordernumber=1000&orderstatus=02&authCode=123456&eci=VISA3D&authRRN=012345678901&storeid=101010&approveamount=500¤cy=USD&orderdate=2007-12-01.12.35.40.123456' 58 | end 59 | end 60 | -------------------------------------------------------------------------------- /test/remote/gateways/remote_exact_test.rb: -------------------------------------------------------------------------------- 1 | require File.dirname(__FILE__) + '/../../test_helper' 2 | 3 | class RemoteExactTest < Test::Unit::TestCase 4 | 5 | def setup 6 | 7 | @gateway = ExactGateway.new(fixtures(:exact)) 8 | @credit_card = credit_card 9 | @amount = 100 10 | @options = { 11 | :order_id => '1', 12 | :billing_address => address, 13 | :description => 'Store Purchase' 14 | } 15 | end 16 | 17 | def test_successful_purchase 18 | assert response = @gateway.purchase(@amount, @credit_card, @options) 19 | assert_match /Transaction Normal/, response.message 20 | assert_success response 21 | end 22 | 23 | def test_unsuccessful_purchase 24 | # ask for error 13 response (Amount Error) via dollar amount 5,000 + error 25 | @amount = 501300 26 | assert response = @gateway.purchase(@amount, @credit_card, @options ) 27 | assert_match /Transaction Normal/, response.message 28 | assert_failure response 29 | end 30 | 31 | def test_purchase_and_credit 32 | assert purchase = @gateway.purchase(@amount, @credit_card, @options) 33 | assert_success purchase 34 | assert purchase.authorization 35 | assert credit = @gateway.credit(@amount, purchase.authorization) 36 | assert_success credit 37 | end 38 | 39 | def test_authorize_and_capture 40 | assert auth = @gateway.authorize(@amount, @credit_card, @options) 41 | assert_success auth 42 | assert auth.authorization 43 | assert capture = @gateway.capture(@amount, auth.authorization) 44 | assert_success capture 45 | end 46 | 47 | def test_failed_capture 48 | assert response = @gateway.capture(@amount, '') 49 | assert_failure response 50 | assert_match /Precondition Failed/i, response.message 51 | end 52 | 53 | def test_invalid_login 54 | gateway = ExactGateway.new( :login => "NotARealUser", 55 | :password => "NotARealPassword" ) 56 | assert response = gateway.purchase(@amount, @credit_card, @options) 57 | assert_equal "Invalid Logon", response.message 58 | assert_failure response 59 | end 60 | end 61 | -------------------------------------------------------------------------------- /test/unit/generators/test_integration_generator.rb: -------------------------------------------------------------------------------- 1 | require File.join(File.dirname(__FILE__), "test_generator_helper.rb") 2 | 3 | class TestIntegrationGenerator < Test::Unit::TestCase 4 | include RubiGen::GeneratorTestHelper 5 | 6 | def setup 7 | bare_setup 8 | end 9 | 10 | def teardown 11 | bare_teardown 12 | end 13 | 14 | # Some generator-related assertions: 15 | # assert_generated_file(name, &block) # block passed the file contents 16 | # assert_directory_exists(name) 17 | # assert_generated_class(name, &block) 18 | # assert_generated_module(name, &block) 19 | # assert_generated_test_for(name, &block) 20 | # The assert_generated_(class|module|test_for) &block is passed the body of the class/module within the file 21 | # assert_has_method(body, *methods) # check that the body has a list of methods (methods with parentheses not supported yet) 22 | # 23 | # Other helper methods are: 24 | # app_root_files - put this in teardown to show files generated by the test method (e.g. p app_root_files) 25 | # bare_setup - place this in setup method to create the APP_ROOT folder for each test 26 | # bare_teardown - place this in teardown method to destroy the TMP_ROOT or APP_ROOT folder after each test 27 | 28 | def test_generator_without_options 29 | name = 'miracle' 30 | 31 | run_generator('integration', [ name ], sources) 32 | 33 | lib_dir = IntegrationGenerator::BASE_DIR + name 34 | test_dir = IntegrationGenerator::TEST_DIR 35 | assert_generated_file("#{lib_dir}.rb") 36 | assert_generated_file(lib_dir + "/helper.rb") 37 | assert_generated_file(lib_dir + "/notification.rb") 38 | 39 | assert_generated_file(test_dir + "#{name}_module_test.rb") 40 | assert_generated_file(test_dir + "helpers/#{name}_helper_test.rb") 41 | assert_generated_file(test_dir + "notifications/#{name}_notification_test.rb") 42 | end 43 | 44 | private 45 | def sources 46 | [RubiGen::PathSource.new(:test, File.join(File.dirname(__FILE__),"..", generator_path)) 47 | ] 48 | end 49 | 50 | def generator_path 51 | "generators" 52 | end 53 | end 54 | -------------------------------------------------------------------------------- /lib/active_merchant/billing/base.rb: -------------------------------------------------------------------------------- 1 | module ActiveMerchant #:nodoc: 2 | module Billing #:nodoc: 3 | module Base 4 | # Set ActiveMerchant gateways in test mode. 5 | # 6 | # ActiveMerchant::Billing::Base.gateway_mode = :test 7 | mattr_accessor :gateway_mode 8 | 9 | # Set ActiveMerchant gateways in test mode. 10 | # 11 | # ActiveMerchant::Billing::Base.gateway_mode = :test 12 | mattr_accessor :integration_mode 13 | 14 | # Set both the mode of both the gateways and integrations 15 | # at once 16 | mattr_reader :mode 17 | 18 | def self.mode=(mode) 19 | @@mode = mode 20 | self.gateway_mode = mode 21 | self.integration_mode = mode 22 | end 23 | 24 | self.mode = :production 25 | 26 | # Return the matching gateway for the provider 27 | # * bogus: BogusGateway - Does nothing (for testing) 28 | # * moneris: MonerisGateway 29 | # * authorize_net: AuthorizeNetGateway 30 | # * trust_commerce: TrustCommerceGateway 31 | # 32 | # ActiveMerchant::Billing::Base.gateway('moneris').new 33 | def self.gateway(name) 34 | Billing.const_get("#{name.to_s.downcase}_gateway".camelize) 35 | end 36 | 37 | 38 | # Return the matching integration module 39 | # You can then get the notification from the module 40 | # * bogus: Bogus - Does nothing (for testing) 41 | # * chronopay: Chronopay - Does nothing (for testing) 42 | # * paypal: Chronopay - Does nothing (for testing) 43 | # 44 | # chronopay = ActiveMerchant::Billing::Base.integration('chronopay') 45 | # notification = chronopay.notification(raw_post) 46 | # 47 | def self.integration(name) 48 | Billing::Integrations.const_get("#{name.to_s.downcase}".camelize) 49 | end 50 | 51 | # A check to see if we're in test mode 52 | def self.test? 53 | self.gateway_mode == :test 54 | end 55 | end 56 | end 57 | end 58 | -------------------------------------------------------------------------------- /lib/active_merchant/billing/integrations/notification.rb: -------------------------------------------------------------------------------- 1 | module ActiveMerchant #:nodoc: 2 | module Billing #:nodoc: 3 | module Integrations #:nodoc: 4 | class Notification 5 | attr_accessor :params 6 | attr_accessor :raw 7 | 8 | # set this to an array in the subclass, to specify which IPs are allowed to send requests 9 | class_inheritable_accessor :production_ips 10 | 11 | def initialize(post, options = {}) 12 | @options = options 13 | empty! 14 | parse(post) 15 | end 16 | 17 | def status 18 | raise NotImplementedError, "Must implement this method in the subclass" 19 | end 20 | 21 | # the money amount we received in X.2 decimal. 22 | def gross 23 | raise NotImplementedError, "Must implement this method in the subclass" 24 | end 25 | 26 | def gross_cents 27 | (gross.to_f * 100.0).round 28 | end 29 | 30 | # This combines the gross and currency and returns a proper Money object. 31 | # this requires the money library located at http://dist.leetsoft.com/api/money 32 | def amount 33 | return Money.new(gross_cents, currency) rescue ArgumentError 34 | return Money.new(gross_cents) # maybe you have an own money object which doesn't take a currency? 35 | end 36 | 37 | # reset the notification. 38 | def empty! 39 | @params = Hash.new 40 | @raw = "" 41 | end 42 | 43 | # Check if the request comes from an official IP 44 | def valid_sender?(ip) 45 | return true if ActiveMerchant::Billing::Base.integration_mode == :test || production_ips.blank? 46 | production_ips.include?(ip) 47 | end 48 | 49 | private 50 | 51 | # Take the posted data and move the relevant data into a hash 52 | def parse(post) 53 | @raw = post.to_s 54 | for line in @raw.split('&') 55 | key, value = *line.scan( %r{^([A-Za-z0-9_.]+)\=(.*)$} ).flatten 56 | params[key] = CGI.unescape(value) 57 | end 58 | end 59 | end 60 | end 61 | end 62 | end 63 | -------------------------------------------------------------------------------- /test/unit/integrations/helpers/chronopay_helper_test.rb: -------------------------------------------------------------------------------- 1 | require File.dirname(__FILE__) + '/../../../test_helper' 2 | 3 | class ChronopayHelperTest < Test::Unit::TestCase 4 | include ActiveMerchant::Billing::Integrations 5 | 6 | def setup 7 | @helper = Chronopay::Helper.new('order-500','003176-0001-0001', :amount => 500, :currency => 'CAD') 8 | end 9 | 10 | def test_basic_helper_fields 11 | assert_field 'cs1', 'order-500' 12 | assert_field 'product_id', '003176-0001-0001' 13 | assert_field 'product_price', '500' 14 | assert_field 'product_price_currency', 'CAD' 15 | end 16 | 17 | def test_customer_fields 18 | @helper.customer :first_name => 'Cody', :last_name => 'Fauser' 19 | assert_field 'f_name', 'Cody' 20 | assert_field 's_name', 'Fauser' 21 | end 22 | 23 | def test_address_mapping 24 | @helper.billing_address :country => 'CAN', 25 | :address1 => '1 My Street', 26 | :city => 'Ottawa', 27 | :state => 'On', 28 | :zip => '90210' 29 | 30 | assert_field 'country', 'CAN' 31 | assert_field 'street', '1 My Street' 32 | assert_field 'state', 'On' 33 | assert_field 'zip', '90210' 34 | end 35 | 36 | def test_country_code_mapping 37 | @helper.billing_address :country => 'CA' 38 | assert_field 'country', 'CAN' 39 | end 40 | 41 | def test_province_code_mapping_non_us 42 | @helper.billing_address :country => 'DE', :state => 'Berlin' 43 | assert_field 'country', 'DEU' 44 | assert_field 'state', 'XX' 45 | end 46 | 47 | def test_state_code_mapping_us 48 | @helper.billing_address :country => 'US', :state => 'CA' 49 | assert_field 'country', 'USA' 50 | assert_field 'state', 'CA' 51 | end 52 | 53 | def test_unknown_mapping 54 | assert_nothing_raised do 55 | @helper.company_address :address => '500 Dwemthy Fox Road' 56 | end 57 | end 58 | 59 | def test_setting_invalid_address_field 60 | fields = @helper.fields.dup 61 | @helper.billing_address :street => 'My Street' 62 | 63 | # Will still set the state code to 'XX' 64 | fields['state'] = 'XX' 65 | assert_equal fields, @helper.fields 66 | end 67 | end 68 | -------------------------------------------------------------------------------- /generators/integration/integration_generator.rb: -------------------------------------------------------------------------------- 1 | class IntegrationGenerator < RubiGen::Base 2 | BASE_DIR = "lib/active_merchant/billing/integrations/" 3 | TEST_DIR = "test/unit/integrations/" 4 | 5 | default_options :author => nil 6 | 7 | attr_reader :name 8 | 9 | def initialize(runtime_args, runtime_options = {}) 10 | super 11 | usage if args.size < 1 12 | @name = args.shift 13 | extract_options 14 | end 15 | 16 | def class_name 17 | name.classify 18 | end 19 | 20 | def lib_dir 21 | BASE_DIR + name 22 | end 23 | 24 | def manifest 25 | record do |m| 26 | # Ensure appropriate folder(s) exists 27 | m.directory lib_dir 28 | m.directory TEST_DIR 29 | m.directory TEST_DIR + "helpers" 30 | m.directory TEST_DIR + "notifications" 31 | 32 | m.template 'integration.rb', "#{lib_dir}.rb" 33 | m.template 'helper.rb', lib_dir + "/helper.rb" 34 | m.template 'notification.rb', lib_dir + "/notification.rb" 35 | 36 | m.template 'module_test.rb', TEST_DIR + "#{name}_module_test.rb" 37 | m.template 'helper_test.rb', TEST_DIR + "helpers/#{name}_helper_test.rb" 38 | m.template 'notification_test.rb', TEST_DIR + "notifications/#{name}_notification_test.rb" 39 | end 40 | end 41 | 42 | protected 43 | def banner 44 | <<-EOS 45 | Creates a ... 46 | 47 | USAGE: #{$0} #{spec.name} name" 48 | EOS 49 | end 50 | 51 | def add_options!(opts) 52 | # opts.separator '' 53 | # opts.separator 'Options:' 54 | # For each option below, place the default 55 | # at the top of the file next to "default_options" 56 | # opts.on("-a", "--author=\"Your Name\"", String, 57 | # "Some comment about this option", 58 | # "Default: none") { |options[:author]| } 59 | # opts.on("-v", "--version", "Show the #{File.basename($0)} version number and quit.") 60 | end 61 | 62 | def extract_options 63 | # for each option, extract it into a local variable (and create an "attr_reader :author" at the top) 64 | # Templates can access these value via the attr_reader-generated methods, but not the 65 | # raw instance variable value. 66 | # @author = options[:author] 67 | end 68 | end -------------------------------------------------------------------------------- /test/unit/gateways/pay_secure_test.rb: -------------------------------------------------------------------------------- 1 | require File.dirname(__FILE__) + '/../../test_helper' 2 | 3 | class PaySecureTest < Test::Unit::TestCase 4 | 5 | def setup 6 | @gateway = PaySecureGateway.new( 7 | :login => 'login', 8 | :password => 'password' 9 | ) 10 | 11 | @credit_card = credit_card 12 | @options = { 13 | :order_id => '1000', 14 | :billing_address => address, 15 | :description => 'Test purchase' 16 | } 17 | @amount = 100 18 | end 19 | 20 | def test_successful_purchase 21 | @gateway.expects(:ssl_post).returns(successful_purchase_response) 22 | assert response = @gateway.purchase(@amount, @credit_card, @options) 23 | assert_instance_of Response, response 24 | assert_success response 25 | assert_equal '2778;SimProxy 54041670', response.authorization 26 | assert response.test? 27 | end 28 | 29 | def test_failed_purchase 30 | @gateway.expects(:ssl_post).returns(failure_response) 31 | assert response = @gateway.purchase(@amount, @credit_card, @options) 32 | assert_instance_of Response, response 33 | assert_equal "Field value '8f796cb29a1be32af5ce12d4ca7425c2' does not match required format.", response.message 34 | assert_failure response 35 | end 36 | 37 | def test_avs_result_not_supported 38 | @gateway.expects(:ssl_post).returns(successful_purchase_response) 39 | 40 | response = @gateway.purchase(@amount, @credit_card, @options) 41 | assert_nil response.avs_result['code'] 42 | end 43 | 44 | def test_cvv_result_not_supported 45 | @gateway.expects(:ssl_post).returns(successful_purchase_response) 46 | 47 | response = @gateway.purchase(@amount, @credit_card, @options) 48 | assert_nil response.cvv_result['code'] 49 | end 50 | 51 | private 52 | def successful_purchase_response 53 | <<-RESPONSE 54 | Status: Accepted 55 | SettlementDate: 2007-10-09 56 | AUTHNUM: 2778 57 | ErrorString: No Error 58 | CardBin: 1 59 | ERROR: 0 60 | TransID: SimProxy 54041670 61 | RESPONSE 62 | end 63 | 64 | def failure_response 65 | <<-RESPONSE 66 | Status: Declined 67 | ErrorString: Field value '8f796cb29a1be32af5ce12d4ca7425c2' does not match required format. 68 | ERROR: 1 69 | RESPONSE 70 | end 71 | end 72 | -------------------------------------------------------------------------------- /lib/tasks/cia.rb: -------------------------------------------------------------------------------- 1 | # Figure out the root path of this app. The default method will assume that 2 | # its the same as the location of the running Rakefile 3 | ROOT = File.expand_path(FileUtils.pwd) + '/' 4 | 5 | # Standard settings, you can override each of them using the environment 6 | # e.g. rake cia EMAIL_TO=your@email.com 7 | # 8 | RAKE_TASK = ENV['RAKE_TASK'] || '' 9 | EMAIL_TO = ENV['EMAIL_TO'] || 'tobi@leetsoft.com' 10 | EMAIL_FROM = ENV['EMAIL_FROM'] || 'CIA