tomriley-active_merchant 1.4.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG +442 -0
- data/CONTRIBUTERS +102 -0
- data/MIT-LICENSE +20 -0
- data/README +134 -0
- data/Rakefile +153 -0
- data/active_merchant.gemspec +15 -0
- data/gem-public_cert.pem +20 -0
- data/init.rb +4 -0
- data/lib/active_merchant/billing/avs_result.rb +98 -0
- data/lib/active_merchant/billing/base.rb +57 -0
- data/lib/active_merchant/billing/check.rb +68 -0
- data/lib/active_merchant/billing/credit_card.rb +159 -0
- data/lib/active_merchant/billing/credit_card_formatting.rb +21 -0
- data/lib/active_merchant/billing/credit_card_methods.rb +125 -0
- data/lib/active_merchant/billing/cvv_result.rb +38 -0
- data/lib/active_merchant/billing/expiry_date.rb +28 -0
- data/lib/active_merchant/billing/gateway.rb +158 -0
- data/lib/active_merchant/billing/gateways/authorize_net.rb +646 -0
- data/lib/active_merchant/billing/gateways/authorize_net_cim.rb +702 -0
- data/lib/active_merchant/billing/gateways/beanstream/beanstream_core.rb +233 -0
- data/lib/active_merchant/billing/gateways/beanstream.rb +102 -0
- data/lib/active_merchant/billing/gateways/beanstream_interac.rb +54 -0
- data/lib/active_merchant/billing/gateways/bogus.rb +98 -0
- data/lib/active_merchant/billing/gateways/braintree.rb +17 -0
- data/lib/active_merchant/billing/gateways/card_stream.rb +230 -0
- data/lib/active_merchant/billing/gateways/cyber_source.rb +406 -0
- data/lib/active_merchant/billing/gateways/data_cash.rb +595 -0
- data/lib/active_merchant/billing/gateways/efsnet.rb +229 -0
- data/lib/active_merchant/billing/gateways/eway.rb +272 -0
- data/lib/active_merchant/billing/gateways/exact.rb +222 -0
- data/lib/active_merchant/billing/gateways/instapay.rb +164 -0
- data/lib/active_merchant/billing/gateways/linkpoint.rb +396 -0
- data/lib/active_merchant/billing/gateways/merchant_e_solutions.rb +154 -0
- data/lib/active_merchant/billing/gateways/modern_payments.rb +36 -0
- data/lib/active_merchant/billing/gateways/modern_payments_cim.rb +214 -0
- data/lib/active_merchant/billing/gateways/moneris.rb +205 -0
- data/lib/active_merchant/billing/gateways/net_registry.rb +189 -0
- data/lib/active_merchant/billing/gateways/netbilling.rb +168 -0
- data/lib/active_merchant/billing/gateways/pay_junction.rb +392 -0
- data/lib/active_merchant/billing/gateways/pay_secure.rb +120 -0
- data/lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb +207 -0
- data/lib/active_merchant/billing/gateways/payflow/payflow_express_response.rb +39 -0
- data/lib/active_merchant/billing/gateways/payflow/payflow_response.rb +13 -0
- data/lib/active_merchant/billing/gateways/payflow.rb +236 -0
- data/lib/active_merchant/billing/gateways/payflow_express.rb +138 -0
- data/lib/active_merchant/billing/gateways/payflow_express_uk.rb +15 -0
- data/lib/active_merchant/billing/gateways/payflow_uk.rb +21 -0
- data/lib/active_merchant/billing/gateways/payment_express.rb +230 -0
- data/lib/active_merchant/billing/gateways/paypal/paypal_common_api.rb +325 -0
- data/lib/active_merchant/billing/gateways/paypal/paypal_express_response.rb +38 -0
- data/lib/active_merchant/billing/gateways/paypal.rb +108 -0
- data/lib/active_merchant/billing/gateways/paypal_ca.rb +13 -0
- data/lib/active_merchant/billing/gateways/paypal_express.rb +130 -0
- data/lib/active_merchant/billing/gateways/paypal_express_common.rb +20 -0
- data/lib/active_merchant/billing/gateways/plugnpay.rb +292 -0
- data/lib/active_merchant/billing/gateways/protx.rb +349 -0
- data/lib/active_merchant/billing/gateways/psigate.rb +214 -0
- data/lib/active_merchant/billing/gateways/psl_card.rb +306 -0
- data/lib/active_merchant/billing/gateways/quickpay.rb +213 -0
- data/lib/active_merchant/billing/gateways/realex.rb +200 -0
- data/lib/active_merchant/billing/gateways/sage/sage_bankcard.rb +88 -0
- data/lib/active_merchant/billing/gateways/sage/sage_core.rb +110 -0
- data/lib/active_merchant/billing/gateways/sage/sage_virtual_check.rb +97 -0
- data/lib/active_merchant/billing/gateways/sage.rb +146 -0
- data/lib/active_merchant/billing/gateways/secure_pay.rb +31 -0
- data/lib/active_merchant/billing/gateways/secure_pay_au.rb +157 -0
- data/lib/active_merchant/billing/gateways/secure_pay_tech.rb +113 -0
- data/lib/active_merchant/billing/gateways/skip_jack.rb +442 -0
- data/lib/active_merchant/billing/gateways/smart_ps.rb +254 -0
- data/lib/active_merchant/billing/gateways/trans_first.rb +127 -0
- data/lib/active_merchant/billing/gateways/transax.rb +26 -0
- data/lib/active_merchant/billing/gateways/trust_commerce.rb +418 -0
- data/lib/active_merchant/billing/gateways/usa_epay.rb +194 -0
- data/lib/active_merchant/billing/gateways/verifi.rb +228 -0
- data/lib/active_merchant/billing/gateways/viaklix.rb +165 -0
- data/lib/active_merchant/billing/gateways/wirecard.rb +318 -0
- data/lib/active_merchant/billing/gateways.rb +3 -0
- data/lib/active_merchant/billing/integrations/action_view_helper.rb +79 -0
- data/lib/active_merchant/billing/integrations/bogus/helper.rb +17 -0
- data/lib/active_merchant/billing/integrations/bogus/notification.rb +11 -0
- data/lib/active_merchant/billing/integrations/bogus/return.rb +10 -0
- data/lib/active_merchant/billing/integrations/bogus.rb +22 -0
- data/lib/active_merchant/billing/integrations/chronopay/helper.rb +81 -0
- data/lib/active_merchant/billing/integrations/chronopay/notification.rb +156 -0
- data/lib/active_merchant/billing/integrations/chronopay/return.rb +10 -0
- data/lib/active_merchant/billing/integrations/chronopay.rb +22 -0
- data/lib/active_merchant/billing/integrations/gestpay/common.rb +42 -0
- data/lib/active_merchant/billing/integrations/gestpay/helper.rb +70 -0
- data/lib/active_merchant/billing/integrations/gestpay/notification.rb +83 -0
- data/lib/active_merchant/billing/integrations/gestpay/return.rb +10 -0
- data/lib/active_merchant/billing/integrations/gestpay.rb +26 -0
- data/lib/active_merchant/billing/integrations/helper.rb +93 -0
- data/lib/active_merchant/billing/integrations/hi_trust/helper.rb +58 -0
- data/lib/active_merchant/billing/integrations/hi_trust/notification.rb +59 -0
- data/lib/active_merchant/billing/integrations/hi_trust/return.rb +67 -0
- data/lib/active_merchant/billing/integrations/hi_trust.rb +26 -0
- data/lib/active_merchant/billing/integrations/nochex/helper.rb +68 -0
- data/lib/active_merchant/billing/integrations/nochex/notification.rb +94 -0
- data/lib/active_merchant/billing/integrations/nochex/return.rb +10 -0
- data/lib/active_merchant/billing/integrations/nochex.rb +87 -0
- data/lib/active_merchant/billing/integrations/notification.rb +62 -0
- data/lib/active_merchant/billing/integrations/paypal/helper.rb +118 -0
- data/lib/active_merchant/billing/integrations/paypal/notification.rb +154 -0
- data/lib/active_merchant/billing/integrations/paypal/return.rb +10 -0
- data/lib/active_merchant/billing/integrations/paypal.rb +40 -0
- data/lib/active_merchant/billing/integrations/quickpay/helper.rb +72 -0
- data/lib/active_merchant/billing/integrations/quickpay/notification.rb +74 -0
- data/lib/active_merchant/billing/integrations/quickpay.rb +18 -0
- data/lib/active_merchant/billing/integrations/return.rb +35 -0
- data/lib/active_merchant/billing/integrations/two_checkout/helper.rb +59 -0
- data/lib/active_merchant/billing/integrations/two_checkout/notification.rb +114 -0
- data/lib/active_merchant/billing/integrations/two_checkout/return.rb +17 -0
- data/lib/active_merchant/billing/integrations/two_checkout.rb +23 -0
- data/lib/active_merchant/billing/integrations.rb +22 -0
- data/lib/active_merchant/billing/response.rb +32 -0
- data/lib/active_merchant/lib/connection.rb +170 -0
- data/lib/active_merchant/lib/country.rb +319 -0
- data/lib/active_merchant/lib/error.rb +4 -0
- data/lib/active_merchant/lib/post_data.rb +22 -0
- data/lib/active_merchant/lib/posts_data.rb +47 -0
- data/lib/active_merchant/lib/requires_parameters.rb +16 -0
- data/lib/active_merchant/lib/utils.rb +18 -0
- data/lib/active_merchant/lib/validateable.rb +76 -0
- data/lib/active_merchant.rb +60 -0
- data/lib/certs/cacert.pem +7815 -0
- data/lib/support/gateway_support.rb +58 -0
- data/script/destroy +14 -0
- data/script/generate +14 -0
- data/test/fixtures.yml +330 -0
- data/test/remote/gateways/remote_authorize_net_cim_test.rb +459 -0
- data/test/remote/gateways/remote_authorize_net_test.rb +145 -0
- data/test/remote/gateways/remote_beanstream_interac_test.rb +53 -0
- data/test/remote/gateways/remote_beanstream_test.rb +150 -0
- data/test/remote/gateways/remote_braintree_test.rb +154 -0
- data/test/remote/gateways/remote_card_stream_test.rb +148 -0
- data/test/remote/gateways/remote_cyber_source_test.rb +144 -0
- data/test/remote/gateways/remote_data_cash_test.rb +357 -0
- data/test/remote/gateways/remote_efsnet_test.rb +81 -0
- data/test/remote/gateways/remote_eway_test.rb +74 -0
- data/test/remote/gateways/remote_exact_test.rb +60 -0
- data/test/remote/gateways/remote_instapay_test.rb +61 -0
- data/test/remote/gateways/remote_linkpoint_test.rb +112 -0
- data/test/remote/gateways/remote_merchant_e_solutions_test.rb +173 -0
- data/test/remote/gateways/remote_modern_payments_cim_test.rb +58 -0
- data/test/remote/gateways/remote_modern_payments_test.rb +43 -0
- data/test/remote/gateways/remote_moneris_test.rb +82 -0
- data/test/remote/gateways/remote_net_registry_test.rb +85 -0
- data/test/remote/gateways/remote_netbilling_test.rb +70 -0
- data/test/remote/gateways/remote_pay_junction_test.rb +143 -0
- data/test/remote/gateways/remote_pay_secure_test.rb +39 -0
- data/test/remote/gateways/remote_payflow_express_test.rb +50 -0
- data/test/remote/gateways/remote_payflow_test.rb +237 -0
- data/test/remote/gateways/remote_payflow_uk_test.rb +173 -0
- data/test/remote/gateways/remote_payment_express_test.rb +136 -0
- data/test/remote/gateways/remote_paypal_express_test.rb +49 -0
- data/test/remote/gateways/remote_paypal_test.rb +167 -0
- data/test/remote/gateways/remote_plugnpay_test.rb +72 -0
- data/test/remote/gateways/remote_protx_test.rb +219 -0
- data/test/remote/gateways/remote_psigate_test.rb +50 -0
- data/test/remote/gateways/remote_psl_card_test.rb +125 -0
- data/test/remote/gateways/remote_quickpay_test.rb +190 -0
- data/test/remote/gateways/remote_realex_test.rb +224 -0
- data/test/remote/gateways/remote_sage_bankcard_test.rb +109 -0
- data/test/remote/gateways/remote_sage_test.rb +87 -0
- data/test/remote/gateways/remote_sage_virtual_check_test.rb +62 -0
- data/test/remote/gateways/remote_secure_pay_au_test.rb +40 -0
- data/test/remote/gateways/remote_secure_pay_tech_test.rb +37 -0
- data/test/remote/gateways/remote_secure_pay_test.rb +28 -0
- data/test/remote/gateways/remote_skipjack_test.rb +105 -0
- data/test/remote/gateways/remote_trans_first_test.rb +34 -0
- data/test/remote/gateways/remote_transax_test.rb +112 -0
- data/test/remote/gateways/remote_trust_commerce_test.rb +152 -0
- data/test/remote/gateways/remote_usa_epay_test.rb +46 -0
- data/test/remote/gateways/remote_verifi_test.rb +107 -0
- data/test/remote/gateways/remote_viaklix_test.rb +43 -0
- data/test/remote/gateways/remote_wirecard_test.rb +111 -0
- data/test/remote/integrations/remote_gestpay_integration_test.rb +37 -0
- data/test/remote/integrations/remote_paypal_integration_test.rb +26 -0
- data/test/test_helper.rb +182 -0
- data/test/unit/avs_result_test.rb +59 -0
- data/test/unit/base_test.rb +55 -0
- data/test/unit/check_test.rb +88 -0
- data/test/unit/connection_test.rb +129 -0
- data/test/unit/country_code_test.rb +33 -0
- data/test/unit/country_test.rb +64 -0
- data/test/unit/credit_card_formatting_test.rb +19 -0
- data/test/unit/credit_card_methods_test.rb +170 -0
- data/test/unit/credit_card_test.rb +318 -0
- data/test/unit/cvv_result_test.rb +33 -0
- data/test/unit/expiry_date_test.rb +21 -0
- data/test/unit/gateways/authorize_net_cim_test.rb +638 -0
- data/test/unit/gateways/authorize_net_test.rb +290 -0
- data/test/unit/gateways/beanstream_interac_test.rb +51 -0
- data/test/unit/gateways/beanstream_test.rb +108 -0
- data/test/unit/gateways/bogus_test.rb +46 -0
- data/test/unit/gateways/braintree_test.rb +126 -0
- data/test/unit/gateways/card_stream_test.rb +90 -0
- data/test/unit/gateways/cyber_source_test.rb +188 -0
- data/test/unit/gateways/data_cash_test.rb +133 -0
- data/test/unit/gateways/efsnet_test.rb +123 -0
- data/test/unit/gateways/eway_test.rb +118 -0
- data/test/unit/gateways/exact_test.rb +156 -0
- data/test/unit/gateways/gateway_test.rb +48 -0
- data/test/unit/gateways/instapay_test.rb +102 -0
- data/test/unit/gateways/linkpoint_test.rb +167 -0
- data/test/unit/gateways/merchant_e_solutions_test.rb +169 -0
- data/test/unit/gateways/modern_payments_cim_test.rb +171 -0
- data/test/unit/gateways/moneris_test.rb +158 -0
- data/test/unit/gateways/net_registry_test.rb +416 -0
- data/test/unit/gateways/netbilling_test.rb +54 -0
- data/test/unit/gateways/pay_junction_test.rb +123 -0
- data/test/unit/gateways/pay_secure_test.rb +71 -0
- data/test/unit/gateways/payflow_express_test.rb +173 -0
- data/test/unit/gateways/payflow_express_uk_test.rb +86 -0
- data/test/unit/gateways/payflow_test.rb +305 -0
- data/test/unit/gateways/payflow_uk_test.rb +30 -0
- data/test/unit/gateways/payment_express_test.rb +195 -0
- data/test/unit/gateways/paypal_express_test.rb +382 -0
- data/test/unit/gateways/paypal_test.rb +520 -0
- data/test/unit/gateways/plugnpay_test.rb +86 -0
- data/test/unit/gateways/protx_test.rb +139 -0
- data/test/unit/gateways/psigate_test.rb +169 -0
- data/test/unit/gateways/psl_card_test.rb +64 -0
- data/test/unit/gateways/quickpay_test.rb +112 -0
- data/test/unit/gateways/realex_test.rb +151 -0
- data/test/unit/gateways/sage_bankcard_test.rb +162 -0
- data/test/unit/gateways/sage_virtual_check_test.rb +71 -0
- data/test/unit/gateways/secure_pay_au_test.rb +207 -0
- data/test/unit/gateways/secure_pay_tech_test.rb +44 -0
- data/test/unit/gateways/secure_pay_test.rb +87 -0
- data/test/unit/gateways/skip_jack_test.rb +133 -0
- data/test/unit/gateways/trans_first_test.rb +112 -0
- data/test/unit/gateways/trust_commerce_test.rb +90 -0
- data/test/unit/gateways/usa_epay_test.rb +128 -0
- data/test/unit/gateways/verifi_test.rb +96 -0
- data/test/unit/gateways/viaklix_test.rb +78 -0
- data/test/unit/gateways/wirecard_test.rb +250 -0
- data/test/unit/generators/test_gateway_generator.rb +46 -0
- data/test/unit/generators/test_generator_helper.rb +20 -0
- data/test/unit/generators/test_integration_generator.rb +53 -0
- data/test/unit/integrations/action_view_helper_test.rb +50 -0
- data/test/unit/integrations/bogus_module_test.rb +20 -0
- data/test/unit/integrations/chronopay_module_test.rb +13 -0
- data/test/unit/integrations/gestpay_module_test.rb +14 -0
- data/test/unit/integrations/helpers/bogus_helper_test.rb +28 -0
- data/test/unit/integrations/helpers/chronopay_helper_test.rb +67 -0
- data/test/unit/integrations/helpers/gestpay_helper_test.rb +100 -0
- data/test/unit/integrations/helpers/hi_trust_helper_test.rb +16 -0
- data/test/unit/integrations/helpers/nochex_helper_test.rb +53 -0
- data/test/unit/integrations/helpers/paypal_helper_test.rb +162 -0
- data/test/unit/integrations/helpers/quickpay_helper_test.rb +40 -0
- data/test/unit/integrations/helpers/two_checkout_helper_test.rb +92 -0
- data/test/unit/integrations/hi_trust_module_test.rb +13 -0
- data/test/unit/integrations/nochex_module_test.rb +13 -0
- data/test/unit/integrations/notifications/chronopay_notification_test.rb +66 -0
- data/test/unit/integrations/notifications/gestpay_notification_test.rb +60 -0
- data/test/unit/integrations/notifications/hi_trust_notification_test.rb +59 -0
- data/test/unit/integrations/notifications/nochex_notification_test.rb +51 -0
- data/test/unit/integrations/notifications/notification_test.rb +54 -0
- data/test/unit/integrations/notifications/paypal_notification_test.rb +85 -0
- data/test/unit/integrations/notifications/quickpay_notification_test.rb +69 -0
- data/test/unit/integrations/notifications/two_checkout_notification_test.rb +55 -0
- data/test/unit/integrations/paypal_module_test.rb +28 -0
- data/test/unit/integrations/quickpay_module_test.rb +9 -0
- data/test/unit/integrations/returns/chronopay_return_test.rb +11 -0
- data/test/unit/integrations/returns/gestpay_return_test.rb +10 -0
- data/test/unit/integrations/returns/hi_trust_return_test.rb +24 -0
- data/test/unit/integrations/returns/nochex_return_test.rb +10 -0
- data/test/unit/integrations/returns/paypal_return_test.rb +10 -0
- data/test/unit/integrations/returns/return_test.rb +11 -0
- data/test/unit/integrations/returns/two_checkout_return_test.rb +24 -0
- data/test/unit/integrations/two_checkout_module_test.rb +13 -0
- data/test/unit/post_data_test.rb +55 -0
- data/test/unit/posts_data_test.rb +48 -0
- data/test/unit/response_test.rb +28 -0
- data/test/unit/utils_test.rb +7 -0
- data/test/unit/validateable_test.rb +60 -0
- metadata +364 -0
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
require 'time'
|
|
2
|
+
require 'date'
|
|
3
|
+
require 'active_merchant/billing/expiry_date'
|
|
4
|
+
|
|
5
|
+
module ActiveMerchant #:nodoc:
|
|
6
|
+
module Billing #:nodoc:
|
|
7
|
+
# == Description
|
|
8
|
+
# This credit card object can be used as a stand alone object. It acts just like an ActiveRecord object
|
|
9
|
+
# but doesn't support the .save method as its not backed by a database.
|
|
10
|
+
#
|
|
11
|
+
# For testing purposes, use the 'bogus' credit card type. This card skips the vast majority of
|
|
12
|
+
# validations. This allows you to focus on your core concerns until you're ready to be more concerned
|
|
13
|
+
# with the details of particular creditcards or your gateway.
|
|
14
|
+
#
|
|
15
|
+
# == Testing With CreditCard
|
|
16
|
+
# Often when testing we don't care about the particulars of a given card type. When using the 'test'
|
|
17
|
+
# mode in your Gateway, there are six different valid card numbers: 1, 2, 3, 'success', 'fail',
|
|
18
|
+
# and 'error'.
|
|
19
|
+
#
|
|
20
|
+
#--
|
|
21
|
+
# For details, see CreditCardMethods#valid_number?
|
|
22
|
+
#++
|
|
23
|
+
#
|
|
24
|
+
# == Example Usage
|
|
25
|
+
# cc = CreditCard.new(
|
|
26
|
+
# :first_name => 'Steve',
|
|
27
|
+
# :last_name => 'Smith',
|
|
28
|
+
# :month => '9',
|
|
29
|
+
# :year => '2010',
|
|
30
|
+
# :type => 'visa',
|
|
31
|
+
# :number => '4242424242424242'
|
|
32
|
+
# )
|
|
33
|
+
#
|
|
34
|
+
# cc.valid? # => true
|
|
35
|
+
# cc.display_number # => XXXX-XXXX-XXXX-4242
|
|
36
|
+
#
|
|
37
|
+
class CreditCard
|
|
38
|
+
include CreditCardMethods
|
|
39
|
+
include Validateable
|
|
40
|
+
|
|
41
|
+
## Attributes
|
|
42
|
+
|
|
43
|
+
cattr_accessor :require_verification_value
|
|
44
|
+
self.require_verification_value = true
|
|
45
|
+
|
|
46
|
+
# Essential attributes for a valid, non-bogus creditcards
|
|
47
|
+
attr_accessor :number, :month, :year, :type, :first_name, :last_name
|
|
48
|
+
|
|
49
|
+
# Required for Switch / Solo cards
|
|
50
|
+
attr_accessor :start_month, :start_year, :issue_number
|
|
51
|
+
|
|
52
|
+
# Optional verification_value (CVV, CVV2 etc). Gateways will try their best to
|
|
53
|
+
# run validation on the passed in value if it is supplied
|
|
54
|
+
attr_accessor :verification_value
|
|
55
|
+
|
|
56
|
+
# Provides proxy access to an expiry date object
|
|
57
|
+
def expiry_date
|
|
58
|
+
ExpiryDate.new(@month, @year)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def expired?
|
|
62
|
+
expiry_date.expired?
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def name?
|
|
66
|
+
first_name? && last_name?
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def first_name?
|
|
70
|
+
!@first_name.blank?
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def last_name?
|
|
74
|
+
!@last_name.blank?
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def name
|
|
78
|
+
"#{@first_name} #{@last_name}"
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def verification_value?
|
|
82
|
+
!@verification_value.blank?
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# Show the card number, with all but last 4 numbers replace with "X". (XXXX-XXXX-XXXX-4338)
|
|
86
|
+
def display_number
|
|
87
|
+
self.class.mask(number)
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def last_digits
|
|
91
|
+
self.class.last_digits(number)
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def validate
|
|
95
|
+
validate_essential_attributes
|
|
96
|
+
|
|
97
|
+
# Bogus card is pretty much for testing purposes. Lets just skip these extra tests if its used
|
|
98
|
+
return if type == 'bogus'
|
|
99
|
+
|
|
100
|
+
validate_card_type
|
|
101
|
+
validate_card_number
|
|
102
|
+
validate_verification_value
|
|
103
|
+
validate_switch_or_solo_attributes
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def self.requires_verification_value?
|
|
107
|
+
require_verification_value
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
private
|
|
111
|
+
|
|
112
|
+
def before_validate #:nodoc:
|
|
113
|
+
self.month = month.to_i
|
|
114
|
+
self.year = year.to_i
|
|
115
|
+
self.start_month = start_month.to_i unless start_month.nil?
|
|
116
|
+
self.start_year = start_year.to_i unless start_year.nil?
|
|
117
|
+
self.number = number.to_s.gsub(/[^\d]/, "")
|
|
118
|
+
self.type.downcase! if type.respond_to?(:downcase)
|
|
119
|
+
self.type = self.class.type?(number) if type.blank?
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def validate_card_number #:nodoc:
|
|
123
|
+
errors.add :number, "is not a valid credit card number" unless CreditCard.valid_number?(number)
|
|
124
|
+
unless errors.on(:number) || errors.on(:type)
|
|
125
|
+
errors.add :type, "is not the correct card type" unless CreditCard.matching_type?(number, type)
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def validate_card_type #:nodoc:
|
|
130
|
+
errors.add :type, "is required" if type.blank?
|
|
131
|
+
errors.add :type, "is invalid" unless CreditCard.card_companies.keys.include?(type)
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def validate_essential_attributes #:nodoc:
|
|
135
|
+
errors.add :first_name, "cannot be empty" if @first_name.blank?
|
|
136
|
+
errors.add :last_name, "cannot be empty" if @last_name.blank?
|
|
137
|
+
errors.add :month, "is not a valid month" unless valid_month?(@month)
|
|
138
|
+
errors.add :year, "expired" if expired?
|
|
139
|
+
errors.add :year, "is not a valid year" unless valid_expiry_year?(@year)
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
def validate_switch_or_solo_attributes #:nodoc:
|
|
143
|
+
if %w[switch solo].include?(type)
|
|
144
|
+
unless valid_month?(@start_month) && valid_start_year?(@start_year) || valid_issue_number?(@issue_number)
|
|
145
|
+
errors.add :start_month, "is invalid" unless valid_month?(@start_month)
|
|
146
|
+
errors.add :start_year, "is invalid" unless valid_start_year?(@start_year)
|
|
147
|
+
errors.add :issue_number, "cannot be empty" unless valid_issue_number?(@issue_number)
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
def validate_verification_value #:nodoc:
|
|
153
|
+
if CreditCard.requires_verification_value?
|
|
154
|
+
errors.add :verification_value, "is required" unless verification_value?
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
end
|
|
158
|
+
end
|
|
159
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
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
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
module ActiveMerchant #:nodoc:
|
|
2
|
+
module Billing #:nodoc:
|
|
3
|
+
# Convenience methods that can be included into a custom Credit Card object, such as an ActiveRecord based Credit Card object.
|
|
4
|
+
module CreditCardMethods
|
|
5
|
+
CARD_COMPANIES = {
|
|
6
|
+
'visa' => /^4\d{12}(\d{3})?$/,
|
|
7
|
+
'master' => /^(5[1-5]\d{4}|677189)\d{10}$/,
|
|
8
|
+
'discover' => /^(6011|65\d{2})\d{12}$/,
|
|
9
|
+
'american_express' => /^3[47]\d{13}$/,
|
|
10
|
+
'diners_club' => /^3(0[0-5]|[68]\d)\d{11}$/,
|
|
11
|
+
'jcb' => /^3528\d{12}$/,
|
|
12
|
+
'switch' => /^6759\d{12}(\d{2,3})?$/,
|
|
13
|
+
'solo' => /^6767\d{12}(\d{2,3})?$/,
|
|
14
|
+
'dankort' => /^5019\d{12}$/,
|
|
15
|
+
'maestro' => /^(5[06-8]|6\d)\d{10,17}$/,
|
|
16
|
+
'forbrugsforeningen' => /^600722\d{10}$/,
|
|
17
|
+
'laser' => /^(6304[89]\d{11}(\d{2,3})?|670695\d{13})$/
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
def self.included(base)
|
|
21
|
+
base.extend(ClassMethods)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def valid_month?(month)
|
|
25
|
+
(1..12).include?(month)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def valid_expiry_year?(year)
|
|
29
|
+
(Time.now.year..Time.now.year + 20).include?(year)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def valid_start_year?(year)
|
|
33
|
+
year.to_s =~ /^\d{4}$/ && year.to_i > 1987
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def valid_issue_number?(number)
|
|
37
|
+
number.to_s =~ /^\d{1,2}$/
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
module ClassMethods
|
|
41
|
+
# Returns true if it validates. Optionally, you can pass a card type as an argument and
|
|
42
|
+
# make sure it is of the correct type.
|
|
43
|
+
#
|
|
44
|
+
# References:
|
|
45
|
+
# - http://perl.about.com/compute/perl/library/nosearch/P073000.htm
|
|
46
|
+
# - http://www.beachnet.com/~hstiles/cardtype.html
|
|
47
|
+
def valid_number?(number)
|
|
48
|
+
valid_test_mode_card_number?(number) ||
|
|
49
|
+
valid_card_number_length?(number) &&
|
|
50
|
+
valid_checksum?(number)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# Regular expressions for the known card companies.
|
|
54
|
+
#
|
|
55
|
+
# References:
|
|
56
|
+
# - http://en.wikipedia.org/wiki/Credit_card_number
|
|
57
|
+
# - http://www.barclaycardbusiness.co.uk/information_zone/processing/bin_rules.html
|
|
58
|
+
def card_companies
|
|
59
|
+
CARD_COMPANIES
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# Returns a string containing the type of card from the list of known information below.
|
|
63
|
+
# Need to check the cards in a particular order, as there is some overlap of the allowable ranges
|
|
64
|
+
#--
|
|
65
|
+
# TODO Refactor this method. We basically need to tighten up the Maestro Regexp.
|
|
66
|
+
#
|
|
67
|
+
# Right now the Maestro regexp overlaps with the MasterCard regexp (IIRC). If we can tighten
|
|
68
|
+
# things up, we can boil this whole thing down to something like...
|
|
69
|
+
#
|
|
70
|
+
# def type?(number)
|
|
71
|
+
# return 'visa' if valid_test_mode_card_number?(number)
|
|
72
|
+
# card_companies.find([nil]) { |type, regexp| number =~ regexp }.first.dup
|
|
73
|
+
# end
|
|
74
|
+
#
|
|
75
|
+
def type?(number)
|
|
76
|
+
return 'bogus' if valid_test_mode_card_number?(number)
|
|
77
|
+
|
|
78
|
+
card_companies.reject { |c,p| c == 'maestro' }.each do |company, pattern|
|
|
79
|
+
return company.dup if number =~ pattern
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
return 'maestro' if number =~ card_companies['maestro']
|
|
83
|
+
|
|
84
|
+
return nil
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def last_digits(number)
|
|
88
|
+
number.to_s.length <= 4 ? number : number.to_s.slice(-4..-1)
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def mask(number)
|
|
92
|
+
"XXXX-XXXX-XXXX-#{last_digits(number)}"
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
# Checks to see if the calculated type matches the specified type
|
|
96
|
+
def matching_type?(number, type)
|
|
97
|
+
type?(number) == type
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
private
|
|
101
|
+
|
|
102
|
+
def valid_card_number_length?(number) #:nodoc:
|
|
103
|
+
number.to_s.length >= 12
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def valid_test_mode_card_number?(number) #:nodoc:
|
|
107
|
+
ActiveMerchant::Billing::Base.test? &&
|
|
108
|
+
%w[1 2 3 success failure error].include?(number.to_s)
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
# Checks the validity of a card number by use of the the Luhn Algorithm.
|
|
112
|
+
# Please see http://en.wikipedia.org/wiki/Luhn_algorithm for details.
|
|
113
|
+
def valid_checksum?(number) #:nodoc:
|
|
114
|
+
sum = 0
|
|
115
|
+
for i in 0..number.length
|
|
116
|
+
weight = number[-1 * (i + 2), 1].to_i * (2 - (i % 2))
|
|
117
|
+
sum += (weight < 10) ? weight : weight - 9
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
(number[-1,1].to_i == (10 - sum % 10) % 10)
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
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
|
|
@@ -0,0 +1,28 @@
|
|
|
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
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
require 'net/http'
|
|
2
|
+
require 'net/https'
|
|
3
|
+
require 'active_merchant/billing/response'
|
|
4
|
+
|
|
5
|
+
module ActiveMerchant #:nodoc:
|
|
6
|
+
module Billing #:nodoc:
|
|
7
|
+
#
|
|
8
|
+
# == Description
|
|
9
|
+
# The Gateway class is the base class for all ActiveMerchant gateway implementations.
|
|
10
|
+
#
|
|
11
|
+
# The standard list of gateway functions that most concrete gateway subclasses implement is:
|
|
12
|
+
#
|
|
13
|
+
# * <tt>purchase(money, creditcard, options = {})</tt>
|
|
14
|
+
# * <tt>authorize(money, creditcard, options = {})</tt>
|
|
15
|
+
# * <tt>capture(money, authorization, options = {})</tt>
|
|
16
|
+
# * <tt>void(identification, options = {})</tt>
|
|
17
|
+
# * <tt>credit(money, identification, options = {})</tt>
|
|
18
|
+
#
|
|
19
|
+
# Some gateways include features for recurring billing
|
|
20
|
+
#
|
|
21
|
+
# * <tt>recurring(money, creditcard, options = {})</tt>
|
|
22
|
+
#
|
|
23
|
+
# Some gateways also support features for storing credit cards:
|
|
24
|
+
#
|
|
25
|
+
# * <tt>store(creditcard, options = {})</tt>
|
|
26
|
+
# * <tt>unstore(identification, options = {})</tt>
|
|
27
|
+
#
|
|
28
|
+
# === Gateway Options
|
|
29
|
+
# The options hash consists of the following options:
|
|
30
|
+
#
|
|
31
|
+
# * <tt>:order_id</tt> - The order number
|
|
32
|
+
# * <tt>:ip</tt> - The IP address of the customer making the purchase
|
|
33
|
+
# * <tt>:customer</tt> - The name, customer number, or other information that identifies the customer
|
|
34
|
+
# * <tt>:invoice</tt> - The invoice number
|
|
35
|
+
# * <tt>:merchant</tt> - The name or description of the merchant offering the product
|
|
36
|
+
# * <tt>:description</tt> - A description of the transaction
|
|
37
|
+
# * <tt>:email</tt> - The email address of the customer
|
|
38
|
+
# * <tt>:currency</tt> - The currency of the transaction. Only important when you are using a currency that is not the default with a gateway that supports multiple currencies.
|
|
39
|
+
# * <tt>:billing_address</tt> - A hash containing the billing address of the customer.
|
|
40
|
+
# * <tt>:shipping_address</tt> - A hash containing the shipping address of the customer.
|
|
41
|
+
#
|
|
42
|
+
# The <tt>:billing_address</tt>, and <tt>:shipping_address</tt> hashes can have the following keys:
|
|
43
|
+
#
|
|
44
|
+
# * <tt>:name</tt> - The full name of the customer.
|
|
45
|
+
# * <tt>:company</tt> - The company name of the customer.
|
|
46
|
+
# * <tt>:address1</tt> - The primary street address of the customer.
|
|
47
|
+
# * <tt>:address2</tt> - Additional line of address information.
|
|
48
|
+
# * <tt>:city</tt> - The city of the customer.
|
|
49
|
+
# * <tt>:state</tt> - The state of the customer. The 2 digit code for US and Canadian addresses. The full name of the state or province for foreign addresses.
|
|
50
|
+
# * <tt>:country</tt> - The [ISO 3166-1-alpha-2 code](http://www.iso.org/iso/country_codes/iso_3166_code_lists/english_country_names_and_code_elements.htm) for the customer.
|
|
51
|
+
# * <tt>:zip</tt> - The zip or postal code of the customer.
|
|
52
|
+
# * <tt>:phone</tt> - The phone number of the customer.
|
|
53
|
+
#
|
|
54
|
+
# == Implmenting new gateways
|
|
55
|
+
#
|
|
56
|
+
# See the {ActiveMerchant Guide to Contributing}[http://code.google.com/p/activemerchant/wiki/Contributing]
|
|
57
|
+
#
|
|
58
|
+
class Gateway
|
|
59
|
+
include PostsData
|
|
60
|
+
include RequiresParameters
|
|
61
|
+
include CreditCardFormatting
|
|
62
|
+
include Utils
|
|
63
|
+
|
|
64
|
+
DEBIT_CARDS = [ :switch, :solo ]
|
|
65
|
+
|
|
66
|
+
cattr_reader :implementations
|
|
67
|
+
@@implementations = []
|
|
68
|
+
|
|
69
|
+
def self.inherited(subclass)
|
|
70
|
+
super
|
|
71
|
+
@@implementations << subclass
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# The format of the amounts used by the gateway
|
|
75
|
+
# :dollars => '12.50'
|
|
76
|
+
# :cents => '1250'
|
|
77
|
+
class_inheritable_accessor :money_format
|
|
78
|
+
self.money_format = :dollars
|
|
79
|
+
|
|
80
|
+
# The default currency for the transactions if no currency is provided
|
|
81
|
+
class_inheritable_accessor :default_currency
|
|
82
|
+
|
|
83
|
+
# The countries of merchants the gateway supports
|
|
84
|
+
class_inheritable_accessor :supported_countries
|
|
85
|
+
self.supported_countries = []
|
|
86
|
+
|
|
87
|
+
# The supported card types for the gateway
|
|
88
|
+
class_inheritable_accessor :supported_cardtypes
|
|
89
|
+
self.supported_cardtypes = []
|
|
90
|
+
|
|
91
|
+
class_inheritable_accessor :homepage_url
|
|
92
|
+
class_inheritable_accessor :display_name
|
|
93
|
+
|
|
94
|
+
# The application making the calls to the gateway
|
|
95
|
+
# Useful for things like the PayPal build notation (BN) id fields
|
|
96
|
+
superclass_delegating_accessor :application_id
|
|
97
|
+
self.application_id = 'ActiveMerchant'
|
|
98
|
+
|
|
99
|
+
attr_reader :options
|
|
100
|
+
|
|
101
|
+
# Use this method to check if your gateway of interest supports a credit card of some type
|
|
102
|
+
def self.supports?(card_type)
|
|
103
|
+
supported_cardtypes.include?(card_type.to_sym)
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def self.card_brand(source)
|
|
107
|
+
result = source.respond_to?(:brand) ? source.brand : source.type
|
|
108
|
+
result.to_s.downcase
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def card_brand(source)
|
|
112
|
+
self.class.card_brand(source)
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
# Initialize a new gateway.
|
|
116
|
+
#
|
|
117
|
+
# See the documentation for the gateway you will be using to make sure there are no other
|
|
118
|
+
# required options.
|
|
119
|
+
def initialize(options = {})
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
# Are we running in test mode?
|
|
123
|
+
def test?
|
|
124
|
+
Base.gateway_mode == :test
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
private # :nodoc: all
|
|
128
|
+
|
|
129
|
+
def name
|
|
130
|
+
self.class.name.scan(/\:\:(\w+)Gateway/).flatten.first
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
def amount(money)
|
|
134
|
+
return nil if money.nil?
|
|
135
|
+
cents = money.respond_to?(:cents) ? money.cents : money
|
|
136
|
+
|
|
137
|
+
if money.is_a?(String) or cents.to_i < 0
|
|
138
|
+
raise ArgumentError, 'money amount must be either a Money object or a positive integer in cents.'
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
if self.money_format == :cents
|
|
142
|
+
cents.to_s
|
|
143
|
+
else
|
|
144
|
+
sprintf("%.2f", cents.to_f / 100)
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
def currency(money)
|
|
149
|
+
money.respond_to?(:currency) ? money.currency : self.default_currency
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
def requires_start_date_or_issue_number?(credit_card)
|
|
153
|
+
return false if card_brand(credit_card).blank?
|
|
154
|
+
DEBIT_CARDS.include?(card_brand(credit_card).to_sym)
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
end
|
|
158
|
+
end
|