start_activemerchant 1.50.0
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.
- checksums.yaml +7 -0
- data/CHANGELOG +1769 -0
- data/CONTRIBUTORS +540 -0
- data/MIT-LICENSE +20 -0
- data/README.md +226 -0
- data/lib/active_merchant.rb +67 -0
- data/lib/active_merchant/billing.rb +15 -0
- data/lib/active_merchant/billing/apple_pay_payment_token.rb +22 -0
- data/lib/active_merchant/billing/avs_result.rb +98 -0
- data/lib/active_merchant/billing/base.rb +72 -0
- data/lib/active_merchant/billing/check.rb +76 -0
- data/lib/active_merchant/billing/compatibility.rb +120 -0
- data/lib/active_merchant/billing/credit_card.rb +404 -0
- data/lib/active_merchant/billing/credit_card_formatting.rb +24 -0
- data/lib/active_merchant/billing/credit_card_methods.rb +195 -0
- data/lib/active_merchant/billing/cvv_result.rb +38 -0
- data/lib/active_merchant/billing/gateway.rb +291 -0
- data/lib/active_merchant/billing/gateways.rb +14 -0
- data/lib/active_merchant/billing/gateways/allied_wallet.rb +203 -0
- data/lib/active_merchant/billing/gateways/app55.rb +176 -0
- data/lib/active_merchant/billing/gateways/authorize_net.rb +510 -0
- data/lib/active_merchant/billing/gateways/authorize_net_arb.rb +417 -0
- data/lib/active_merchant/billing/gateways/authorize_net_cim.rb +976 -0
- data/lib/active_merchant/billing/gateways/axcessms.rb +181 -0
- data/lib/active_merchant/billing/gateways/balanced.rb +256 -0
- data/lib/active_merchant/billing/gateways/bank_frick.rb +225 -0
- data/lib/active_merchant/billing/gateways/banwire.rb +105 -0
- data/lib/active_merchant/billing/gateways/barclays_epdq.rb +314 -0
- data/lib/active_merchant/billing/gateways/barclays_epdq_extra_plus.rb +15 -0
- data/lib/active_merchant/billing/gateways/be2bill.rb +131 -0
- data/lib/active_merchant/billing/gateways/beanstream.rb +192 -0
- data/lib/active_merchant/billing/gateways/beanstream/beanstream_core.rb +389 -0
- data/lib/active_merchant/billing/gateways/beanstream_interac.rb +58 -0
- data/lib/active_merchant/billing/gateways/blue_pay.rb +506 -0
- data/lib/active_merchant/billing/gateways/bogus.rb +140 -0
- data/lib/active_merchant/billing/gateways/borgun.rb +211 -0
- data/lib/active_merchant/billing/gateways/bpoint.rb +277 -0
- data/lib/active_merchant/billing/gateways/braintree.rb +19 -0
- data/lib/active_merchant/billing/gateways/braintree/braintree_common.rb +9 -0
- data/lib/active_merchant/billing/gateways/braintree_blue.rb +574 -0
- data/lib/active_merchant/billing/gateways/braintree_orange.rb +20 -0
- data/lib/active_merchant/billing/gateways/bridge_pay.rb +189 -0
- data/lib/active_merchant/billing/gateways/card_save.rb +23 -0
- data/lib/active_merchant/billing/gateways/card_stream.rb +238 -0
- data/lib/active_merchant/billing/gateways/cashnet.rb +202 -0
- data/lib/active_merchant/billing/gateways/cc5.rb +201 -0
- data/lib/active_merchant/billing/gateways/cecabank.rb +229 -0
- data/lib/active_merchant/billing/gateways/cenpos.rb +262 -0
- data/lib/active_merchant/billing/gateways/certo_direct.rb +278 -0
- data/lib/active_merchant/billing/gateways/checkout.rb +216 -0
- data/lib/active_merchant/billing/gateways/checkout_v2.rb +200 -0
- data/lib/active_merchant/billing/gateways/commercegate.rb +143 -0
- data/lib/active_merchant/billing/gateways/conekta.rb +210 -0
- data/lib/active_merchant/billing/gateways/cyber_source.rb +720 -0
- data/lib/active_merchant/billing/gateways/data_cash.rb +600 -0
- data/lib/active_merchant/billing/gateways/dibs.rb +206 -0
- data/lib/active_merchant/billing/gateways/efsnet.rb +219 -0
- data/lib/active_merchant/billing/gateways/elavon.rb +348 -0
- data/lib/active_merchant/billing/gateways/epay.rb +274 -0
- data/lib/active_merchant/billing/gateways/evo_ca.rb +308 -0
- data/lib/active_merchant/billing/gateways/eway.rb +214 -0
- data/lib/active_merchant/billing/gateways/eway_managed.rb +291 -0
- data/lib/active_merchant/billing/gateways/eway_rapid.rb +522 -0
- data/lib/active_merchant/billing/gateways/exact.rb +227 -0
- data/lib/active_merchant/billing/gateways/ezic.rb +206 -0
- data/lib/active_merchant/billing/gateways/fat_zebra.rb +213 -0
- data/lib/active_merchant/billing/gateways/federated_canada.rb +160 -0
- data/lib/active_merchant/billing/gateways/finansbank.rb +23 -0
- data/lib/active_merchant/billing/gateways/first_giving.rb +143 -0
- data/lib/active_merchant/billing/gateways/first_pay.rb +160 -0
- data/lib/active_merchant/billing/gateways/firstdata_e4.rb +413 -0
- data/lib/active_merchant/billing/gateways/flo2cash.rb +215 -0
- data/lib/active_merchant/billing/gateways/flo2cash_simple.rb +20 -0
- data/lib/active_merchant/billing/gateways/garanti.rb +261 -0
- data/lib/active_merchant/billing/gateways/global_transport.rb +179 -0
- data/lib/active_merchant/billing/gateways/hdfc.rb +207 -0
- data/lib/active_merchant/billing/gateways/hps.rb +287 -0
- data/lib/active_merchant/billing/gateways/iats_payments.rb +277 -0
- data/lib/active_merchant/billing/gateways/ideal/ideal_base.rb +246 -0
- data/lib/active_merchant/billing/gateways/ideal/ideal_rabobank.pem +13 -0
- data/lib/active_merchant/billing/gateways/ideal/ideal_response.rb +29 -0
- data/lib/active_merchant/billing/gateways/ideal_rabobank.rb +66 -0
- data/lib/active_merchant/billing/gateways/inspire.rb +219 -0
- data/lib/active_merchant/billing/gateways/instapay.rb +163 -0
- data/lib/active_merchant/billing/gateways/ipp.rb +175 -0
- data/lib/active_merchant/billing/gateways/iridium.rb +457 -0
- data/lib/active_merchant/billing/gateways/itransact.rb +448 -0
- data/lib/active_merchant/billing/gateways/jetpay.rb +275 -0
- data/lib/active_merchant/billing/gateways/linkpoint.rb +438 -0
- data/lib/active_merchant/billing/gateways/litle.rb +345 -0
- data/lib/active_merchant/billing/gateways/maxipago.rb +197 -0
- data/lib/active_merchant/billing/gateways/merchant_e_solutions.rb +170 -0
- data/lib/active_merchant/billing/gateways/merchant_one.rb +114 -0
- data/lib/active_merchant/billing/gateways/merchant_partners.rb +245 -0
- data/lib/active_merchant/billing/gateways/merchant_ware.rb +319 -0
- data/lib/active_merchant/billing/gateways/merchant_ware_version_four.rb +268 -0
- data/lib/active_merchant/billing/gateways/merchant_warrior.rb +195 -0
- data/lib/active_merchant/billing/gateways/mercury.rb +326 -0
- data/lib/active_merchant/billing/gateways/metrics_global.rb +303 -0
- data/lib/active_merchant/billing/gateways/migs.rb +280 -0
- data/lib/active_merchant/billing/gateways/migs/migs_codes.rb +100 -0
- data/lib/active_merchant/billing/gateways/modern_payments.rb +37 -0
- data/lib/active_merchant/billing/gateways/modern_payments_cim.rb +219 -0
- data/lib/active_merchant/billing/gateways/monei.rb +307 -0
- data/lib/active_merchant/billing/gateways/moneris.rb +309 -0
- data/lib/active_merchant/billing/gateways/moneris_us.rb +298 -0
- data/lib/active_merchant/billing/gateways/money_movers.rb +152 -0
- data/lib/active_merchant/billing/gateways/nab_transact.rb +290 -0
- data/lib/active_merchant/billing/gateways/net_registry.rb +198 -0
- data/lib/active_merchant/billing/gateways/netaxept.rb +181 -0
- data/lib/active_merchant/billing/gateways/netbilling.rb +224 -0
- data/lib/active_merchant/billing/gateways/netpay.rb +223 -0
- data/lib/active_merchant/billing/gateways/network_merchants.rb +242 -0
- data/lib/active_merchant/billing/gateways/nmi.rb +256 -0
- data/lib/active_merchant/billing/gateways/ogone.rb +435 -0
- data/lib/active_merchant/billing/gateways/omise.rb +319 -0
- data/lib/active_merchant/billing/gateways/openpay.rb +194 -0
- data/lib/active_merchant/billing/gateways/optimal_payment.rb +314 -0
- data/lib/active_merchant/billing/gateways/orbital.rb +834 -0
- data/lib/active_merchant/billing/gateways/orbital/orbital_soft_descriptors.rb +47 -0
- data/lib/active_merchant/billing/gateways/pac_net_raven.rb +207 -0
- data/lib/active_merchant/billing/gateways/pago_facil.rb +122 -0
- data/lib/active_merchant/billing/gateways/pay_conex.rb +246 -0
- data/lib/active_merchant/billing/gateways/pay_gate_xml.rb +277 -0
- data/lib/active_merchant/billing/gateways/pay_hub.rb +213 -0
- data/lib/active_merchant/billing/gateways/pay_junction.rb +390 -0
- data/lib/active_merchant/billing/gateways/pay_secure.rb +112 -0
- data/lib/active_merchant/billing/gateways/paybox_direct.rb +188 -0
- data/lib/active_merchant/billing/gateways/payex.rb +412 -0
- data/lib/active_merchant/billing/gateways/payflow.rb +308 -0
- data/lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb +220 -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_express.rb +224 -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 +353 -0
- data/lib/active_merchant/billing/gateways/paymill.rb +282 -0
- data/lib/active_merchant/billing/gateways/paypal.rb +129 -0
- data/lib/active_merchant/billing/gateways/paypal/paypal_common_api.rb +679 -0
- data/lib/active_merchant/billing/gateways/paypal/paypal_express_response.rb +65 -0
- data/lib/active_merchant/billing/gateways/paypal/paypal_recurring_api.rb +262 -0
- data/lib/active_merchant/billing/gateways/paypal_ca.rb +13 -0
- data/lib/active_merchant/billing/gateways/paypal_digital_goods.rb +44 -0
- data/lib/active_merchant/billing/gateways/paypal_express.rb +264 -0
- data/lib/active_merchant/billing/gateways/paypal_express_common.rb +30 -0
- data/lib/active_merchant/billing/gateways/payscout.rb +162 -0
- data/lib/active_merchant/billing/gateways/paystation.rb +199 -0
- data/lib/active_merchant/billing/gateways/payu_in.rb +247 -0
- data/lib/active_merchant/billing/gateways/payway.rb +207 -0
- data/lib/active_merchant/billing/gateways/pin.rb +207 -0
- data/lib/active_merchant/billing/gateways/plugnpay.rb +283 -0
- data/lib/active_merchant/billing/gateways/psigate.rb +216 -0
- data/lib/active_merchant/billing/gateways/psl_card.rb +303 -0
- data/lib/active_merchant/billing/gateways/qbms.rb +292 -0
- data/lib/active_merchant/billing/gateways/quantum.rb +276 -0
- data/lib/active_merchant/billing/gateways/quickbooks.rb +280 -0
- data/lib/active_merchant/billing/gateways/quickpay.rb +26 -0
- data/lib/active_merchant/billing/gateways/quickpay/quickpay_common.rb +188 -0
- data/lib/active_merchant/billing/gateways/quickpay/quickpay_v10.rb +240 -0
- data/lib/active_merchant/billing/gateways/quickpay/quickpay_v4to7.rb +227 -0
- data/lib/active_merchant/billing/gateways/qvalent.rb +179 -0
- data/lib/active_merchant/billing/gateways/realex.rb +298 -0
- data/lib/active_merchant/billing/gateways/redsys.rb +406 -0
- data/lib/active_merchant/billing/gateways/s5.rb +226 -0
- data/lib/active_merchant/billing/gateways/sage.rb +173 -0
- data/lib/active_merchant/billing/gateways/sage/sage_bankcard.rb +89 -0
- data/lib/active_merchant/billing/gateways/sage/sage_core.rb +115 -0
- data/lib/active_merchant/billing/gateways/sage/sage_vault.rb +149 -0
- data/lib/active_merchant/billing/gateways/sage/sage_virtual_check.rb +97 -0
- data/lib/active_merchant/billing/gateways/sage_pay.rb +399 -0
- data/lib/active_merchant/billing/gateways/sallie_mae.rb +143 -0
- data/lib/active_merchant/billing/gateways/secure_net.rb +263 -0
- data/lib/active_merchant/billing/gateways/secure_pay.rb +201 -0
- data/lib/active_merchant/billing/gateways/secure_pay_au.rb +281 -0
- data/lib/active_merchant/billing/gateways/secure_pay_tech.rb +105 -0
- data/lib/active_merchant/billing/gateways/skip_jack.rb +451 -0
- data/lib/active_merchant/billing/gateways/smart_ps.rb +283 -0
- data/lib/active_merchant/billing/gateways/so_easy_pay.rb +194 -0
- data/lib/active_merchant/billing/gateways/spreedly_core.rb +247 -0
- data/lib/active_merchant/billing/gateways/stripe.rb +489 -0
- data/lib/active_merchant/billing/gateways/swipe_checkout.rb +157 -0
- data/lib/active_merchant/billing/gateways/tns.rb +227 -0
- data/lib/active_merchant/billing/gateways/trans_first.rb +126 -0
- data/lib/active_merchant/billing/gateways/transax.rb +23 -0
- data/lib/active_merchant/billing/gateways/transnational.rb +10 -0
- data/lib/active_merchant/billing/gateways/trust_commerce.rb +416 -0
- data/lib/active_merchant/billing/gateways/usa_epay.rb +25 -0
- data/lib/active_merchant/billing/gateways/usa_epay_advanced.rb +1516 -0
- data/lib/active_merchant/billing/gateways/usa_epay_transaction.rb +259 -0
- data/lib/active_merchant/billing/gateways/vanco.rb +280 -0
- data/lib/active_merchant/billing/gateways/verifi.rb +225 -0
- data/lib/active_merchant/billing/gateways/viaklix.rb +183 -0
- data/lib/active_merchant/billing/gateways/webpay.rb +97 -0
- data/lib/active_merchant/billing/gateways/wepay.rb +205 -0
- data/lib/active_merchant/billing/gateways/wirecard.rb +420 -0
- data/lib/active_merchant/billing/gateways/worldpay.rb +331 -0
- data/lib/active_merchant/billing/gateways/worldpay_online_payments.rb +204 -0
- data/lib/active_merchant/billing/gateways/worldpay_us.rb +181 -0
- data/lib/active_merchant/billing/model.rb +30 -0
- data/lib/active_merchant/billing/network_tokenization_credit_card.rb +24 -0
- data/lib/active_merchant/billing/payment_token.rb +21 -0
- data/lib/active_merchant/billing/rails.rb +3 -0
- data/lib/active_merchant/billing/response.rb +92 -0
- data/lib/active_merchant/connection.rb +172 -0
- data/lib/active_merchant/country.rb +332 -0
- data/lib/active_merchant/empty.rb +20 -0
- data/lib/active_merchant/errors.rb +35 -0
- data/lib/active_merchant/network_connection_retries.rb +79 -0
- data/lib/active_merchant/post_data.rb +24 -0
- data/lib/active_merchant/posts_data.rb +84 -0
- data/lib/active_merchant/version.rb +3 -0
- data/lib/activemerchant.rb +1 -0
- data/lib/certs/cacert.pem +3866 -0
- data/lib/support/gateway_support.rb +71 -0
- data/lib/support/outbound_hosts.rb +28 -0
- data/lib/support/ssl_verify.rb +93 -0
- metadata +387 -0
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
module ActiveMerchant #:nodoc:
|
|
2
|
+
module Billing #:nodoc:
|
|
3
|
+
module CreditCardFormatting
|
|
4
|
+
|
|
5
|
+
def expdate(credit_card)
|
|
6
|
+
"#{format(credit_card.month, :two_digits)}#{format(credit_card.year, :two_digits)}"
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
# This method is used to format numerical information pertaining to credit cards.
|
|
10
|
+
#
|
|
11
|
+
# format(2005, :two_digits) # => "05"
|
|
12
|
+
# format(05, :four_digits) # => "0005"
|
|
13
|
+
def format(number, option)
|
|
14
|
+
return '' if number.blank?
|
|
15
|
+
|
|
16
|
+
case option
|
|
17
|
+
when :two_digits ; sprintf("%.2i", number.to_i)[-2..-1]
|
|
18
|
+
when :four_digits ; sprintf("%.4i", number.to_i)[-4..-1]
|
|
19
|
+
else number
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,195 @@
|
|
|
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})?(\d{3})?$/,
|
|
7
|
+
'master' => /^(5[1-5]\d{4}|677189)\d{10}$/,
|
|
8
|
+
'discover' => /^(6011|65\d{2}|64[4-9]\d)\d{12}|(62\d{14})$/,
|
|
9
|
+
'american_express' => /^3[47]\d{13}$/,
|
|
10
|
+
'diners_club' => /^3(0[0-5]|[68]\d)\d{11}$/,
|
|
11
|
+
'jcb' => /^35(28|29|[3-8]\d)\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|6706|6709|6771(?!89))\d{8}(\d{4}|\d{6,7})?$/
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
def self.included(base)
|
|
21
|
+
base.extend(ClassMethods)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def valid_month?(month)
|
|
25
|
+
(1..12).include?(month.to_i)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def valid_expiry_year?(year)
|
|
29
|
+
(Time.now.year..Time.now.year + 20).include?(year.to_i)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def valid_start_year?(year)
|
|
33
|
+
((year.to_s =~ /^\d{4}$/) && (year.to_i > 1987))
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Credit card providers have 3 digit verification values
|
|
37
|
+
# This isn't standardised, these are called various names such as
|
|
38
|
+
# CVC, CVV, CID, CSC and more
|
|
39
|
+
# See: http://en.wikipedia.org/wiki/Card_security_code
|
|
40
|
+
# American Express is the exception with 4 digits
|
|
41
|
+
#
|
|
42
|
+
# Below are links from the card providers with their requirements
|
|
43
|
+
# visa: http://usa.visa.com/personal/security/3-digit-security-code.jsp
|
|
44
|
+
# master: http://www.mastercard.com/ca/merchant/en/getstarted/Anatomy_MasterCard.html
|
|
45
|
+
# jcb: http://www.jcbcard.com/security/info.html
|
|
46
|
+
# diners_club: http://www.dinersclub.com/assets/DinersClub_card_ID_features.pdf
|
|
47
|
+
# discover: https://www.discover.com/credit-cards/help-center/glossary.html
|
|
48
|
+
# american_express: https://online.americanexpress.com/myca/fuidfyp/us/action?request_type=un_fuid&Face=en_US
|
|
49
|
+
def valid_card_verification_value?(cvv, brand)
|
|
50
|
+
cvv.to_s =~ /^\d{#{card_verification_value_length(brand)}}$/
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def card_verification_value_length(brand)
|
|
54
|
+
brand == 'american_express' ? 4 : 3
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def valid_issue_number?(number)
|
|
58
|
+
(number.to_s =~ /^\d{1,2}$/)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
module ClassMethods
|
|
62
|
+
# Returns true if it validates. Optionally, you can pass a card brand as an argument and
|
|
63
|
+
# make sure it is of the correct brand.
|
|
64
|
+
#
|
|
65
|
+
# References:
|
|
66
|
+
# - http://perl.about.com/compute/perl/library/nosearch/P073000.htm
|
|
67
|
+
# - http://www.beachnet.com/~hstiles/cardtype.html
|
|
68
|
+
def valid_number?(number)
|
|
69
|
+
valid_test_mode_card_number?(number) ||
|
|
70
|
+
valid_card_number_length?(number) &&
|
|
71
|
+
valid_checksum?(number)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# Regular expressions for the known card companies.
|
|
75
|
+
#
|
|
76
|
+
# References:
|
|
77
|
+
# - http://en.wikipedia.org/wiki/Credit_card_number
|
|
78
|
+
# - http://www.barclaycardbusiness.co.uk/information_zone/processing/bin_rules.html
|
|
79
|
+
def card_companies
|
|
80
|
+
CARD_COMPANIES
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
# Returns a string containing the brand of card from the list of known information below.
|
|
84
|
+
# Need to check the cards in a particular order, as there is some overlap of the allowable ranges
|
|
85
|
+
#--
|
|
86
|
+
# TODO Refactor this method. We basically need to tighten up the Maestro Regexp.
|
|
87
|
+
#
|
|
88
|
+
# Right now the Maestro regexp overlaps with the MasterCard regexp (IIRC). If we can tighten
|
|
89
|
+
# things up, we can boil this whole thing down to something like...
|
|
90
|
+
#
|
|
91
|
+
# def brand?(number)
|
|
92
|
+
# return 'visa' if valid_test_mode_card_number?(number)
|
|
93
|
+
# card_companies.find([nil]) { |brand, regexp| number =~ regexp }.first.dup
|
|
94
|
+
# end
|
|
95
|
+
#
|
|
96
|
+
def brand?(number)
|
|
97
|
+
return 'bogus' if valid_test_mode_card_number?(number)
|
|
98
|
+
|
|
99
|
+
card_companies.reject { |c,p| c == 'maestro' }.each do |company, pattern|
|
|
100
|
+
return company.dup if number =~ pattern
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
return 'maestro' if number =~ card_companies['maestro']
|
|
104
|
+
|
|
105
|
+
return nil
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def type?(number)
|
|
109
|
+
ActiveMerchant.deprecated "CreditCard#type? is deprecated and will be removed from a future release of ActiveMerchant. Please use CreditCard#brand? instead."
|
|
110
|
+
brand?(number)
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def first_digits(number)
|
|
114
|
+
number.to_s.slice(0,6)
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def last_digits(number)
|
|
118
|
+
number.to_s.length <= 4 ? number : number.to_s.slice(-4..-1)
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def mask(number)
|
|
122
|
+
"XXXX-XXXX-XXXX-#{last_digits(number)}"
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
# Checks to see if the calculated brand matches the specified brand
|
|
126
|
+
def matching_brand?(number, brand)
|
|
127
|
+
brand?(number) == brand
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def matching_type?(number, brand)
|
|
131
|
+
ActiveMerchant.deprecated "CreditCard#matching_type? is deprecated and will be removed from a future release of ActiveMerchant. Please use CreditCard#matching_brand? instead."
|
|
132
|
+
matching_brand?(number, brand)
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
private
|
|
136
|
+
|
|
137
|
+
def valid_card_number_length?(number) #:nodoc:
|
|
138
|
+
number.to_s.length >= 12
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
def valid_test_mode_card_number?(number) #:nodoc:
|
|
142
|
+
ActiveMerchant::Billing::Base.test? &&
|
|
143
|
+
%w[1 2 3 success failure error].include?(number.to_s)
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
ODD_LUHN_VALUE = {
|
|
147
|
+
48 => 0,
|
|
148
|
+
49 => 1,
|
|
149
|
+
50 => 2,
|
|
150
|
+
51 => 3,
|
|
151
|
+
52 => 4,
|
|
152
|
+
53 => 5,
|
|
153
|
+
54 => 6,
|
|
154
|
+
55 => 7,
|
|
155
|
+
56 => 8,
|
|
156
|
+
57 => 9,
|
|
157
|
+
nil => 0
|
|
158
|
+
}.freeze
|
|
159
|
+
|
|
160
|
+
EVEN_LUHN_VALUE = {
|
|
161
|
+
48 => 0, # 0 * 2
|
|
162
|
+
49 => 2, # 1 * 2
|
|
163
|
+
50 => 4, # 2 * 2
|
|
164
|
+
51 => 6, # 3 * 2
|
|
165
|
+
52 => 8, # 4 * 2
|
|
166
|
+
53 => 1, # 5 * 2 - 9
|
|
167
|
+
54 => 3, # 6 * 2 - 9
|
|
168
|
+
55 => 5, # etc ...
|
|
169
|
+
56 => 7,
|
|
170
|
+
57 => 9,
|
|
171
|
+
}.freeze
|
|
172
|
+
|
|
173
|
+
# Checks the validity of a card number by use of the Luhn Algorithm.
|
|
174
|
+
# Please see http://en.wikipedia.org/wiki/Luhn_algorithm for details.
|
|
175
|
+
# This implementation is from the luhn_checksum gem, https://github.com/zendesk/luhn_checksum.
|
|
176
|
+
def valid_checksum?(numbers) #:nodoc:
|
|
177
|
+
sum = 0
|
|
178
|
+
|
|
179
|
+
odd = true
|
|
180
|
+
numbers.reverse.bytes.each do |number|
|
|
181
|
+
if odd
|
|
182
|
+
odd = false
|
|
183
|
+
sum += ODD_LUHN_VALUE[number]
|
|
184
|
+
else
|
|
185
|
+
odd = true
|
|
186
|
+
sum += EVEN_LUHN_VALUE[number]
|
|
187
|
+
end
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
sum % 10 == 0
|
|
191
|
+
end
|
|
192
|
+
end
|
|
193
|
+
end
|
|
194
|
+
end
|
|
195
|
+
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' => 'CVV check flagged transaction as suspicious',
|
|
10
|
+
'I' => 'CVV failed data validation check',
|
|
11
|
+
'M' => 'CVV matches',
|
|
12
|
+
'N' => 'CVV does not match',
|
|
13
|
+
'P' => 'CVV not processed',
|
|
14
|
+
'S' => 'CVV should have been present',
|
|
15
|
+
'U' => 'CVV request unable to be processed by issuer',
|
|
16
|
+
'X' => 'CVV check not supported for card'
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
def self.messages
|
|
20
|
+
MESSAGES
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
attr_reader :code, :message
|
|
24
|
+
|
|
25
|
+
def initialize(code)
|
|
26
|
+
@code = (code.blank? ? nil : code.upcase)
|
|
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,291 @@
|
|
|
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, credit_card, options = {})</tt>
|
|
14
|
+
# * <tt>authorize(money, credit_card, options = {})</tt>
|
|
15
|
+
# * <tt>capture(money, authorization, options = {})</tt>
|
|
16
|
+
# * <tt>void(identification, options = {})</tt>
|
|
17
|
+
# * <tt>refund(money, identification, options = {})</tt>
|
|
18
|
+
# * <tt>verify(credit_card, options = {})</tt>
|
|
19
|
+
#
|
|
20
|
+
# Some gateways also support features for storing credit cards:
|
|
21
|
+
#
|
|
22
|
+
# * <tt>store(credit_card, options = {})</tt>
|
|
23
|
+
# * <tt>unstore(identification, options = {})</tt>
|
|
24
|
+
#
|
|
25
|
+
# === Gateway Options
|
|
26
|
+
# The options hash consists of the following options:
|
|
27
|
+
#
|
|
28
|
+
# * <tt>:order_id</tt> - The order number
|
|
29
|
+
# * <tt>:ip</tt> - The IP address of the customer making the purchase
|
|
30
|
+
# * <tt>:customer</tt> - The name, customer number, or other information that identifies the customer
|
|
31
|
+
# * <tt>:invoice</tt> - The invoice number
|
|
32
|
+
# * <tt>:merchant</tt> - The name or description of the merchant offering the product
|
|
33
|
+
# * <tt>:description</tt> - A description of the transaction
|
|
34
|
+
# * <tt>:email</tt> - The email address of the customer
|
|
35
|
+
# * <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.
|
|
36
|
+
# * <tt>:billing_address</tt> - A hash containing the billing address of the customer.
|
|
37
|
+
# * <tt>:shipping_address</tt> - A hash containing the shipping address of the customer.
|
|
38
|
+
#
|
|
39
|
+
# The <tt>:billing_address</tt>, and <tt>:shipping_address</tt> hashes can have the following keys:
|
|
40
|
+
#
|
|
41
|
+
# * <tt>:name</tt> - The full name of the customer.
|
|
42
|
+
# * <tt>:company</tt> - The company name of the customer.
|
|
43
|
+
# * <tt>:address1</tt> - The primary street address of the customer.
|
|
44
|
+
# * <tt>:address2</tt> - Additional line of address information.
|
|
45
|
+
# * <tt>:city</tt> - The city of the customer.
|
|
46
|
+
# * <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.
|
|
47
|
+
# * <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.
|
|
48
|
+
# * <tt>:zip</tt> - The zip or postal code of the customer.
|
|
49
|
+
# * <tt>:phone</tt> - The phone number of the customer.
|
|
50
|
+
#
|
|
51
|
+
# == Implmenting new gateways
|
|
52
|
+
#
|
|
53
|
+
# See the {ActiveMerchant Guide to Contributing}[https://github.com/activemerchant/active_merchant/wiki/Contributing]
|
|
54
|
+
#
|
|
55
|
+
class Gateway
|
|
56
|
+
include PostsData
|
|
57
|
+
include CreditCardFormatting
|
|
58
|
+
|
|
59
|
+
DEBIT_CARDS = [ :switch, :solo ]
|
|
60
|
+
CURRENCIES_WITHOUT_FRACTIONS = [ 'BIF', 'BYR', 'CLP', 'CVE', 'DJF', 'GNF', 'HUF', 'ISK', 'JPY', 'KMF', 'KRW', 'PYG', 'RWF', 'TWD', 'UGX', 'VND', 'VUV', 'XAF', 'XOF', 'XPF' ]
|
|
61
|
+
|
|
62
|
+
CREDIT_DEPRECATION_MESSAGE = "Support for using credit to refund existing transactions is deprecated and will be removed from a future release of ActiveMerchant. Please use the refund method instead."
|
|
63
|
+
RECURRING_DEPRECATION_MESSAGE = "Recurring functionality in ActiveMerchant is deprecated and will be removed in a future version. Please contact the ActiveMerchant maintainers if you have an interest in taking ownership of a separate gem that continues support for it."
|
|
64
|
+
|
|
65
|
+
# == Standardized Error Codes
|
|
66
|
+
#
|
|
67
|
+
# :incorrect_number - Card number does not comply with ISO/IEC 7812 numbering standard
|
|
68
|
+
# :invalid_number - Card number was not matched by processor
|
|
69
|
+
# :invalid_expiry_date - Expiry date deos not match correct formatting
|
|
70
|
+
# :invalid_cvc - Security codes does not match correct format (3-4 digits)
|
|
71
|
+
# :expired_card - Card number is expired
|
|
72
|
+
# :incorrect_cvc - Secerity code was not matched by the processor
|
|
73
|
+
# :incorrect_zip - Zip code is not in correct format
|
|
74
|
+
# :incorrect_address - Billing address info was not matched by the processor
|
|
75
|
+
# :card_declined - Card number declined by processor
|
|
76
|
+
# :processing_error - Processor error
|
|
77
|
+
# :call_issuer - Transaction requires voice authentication, call issuer
|
|
78
|
+
# :pickup_card - Issuer requests that you pickup the card from merchant
|
|
79
|
+
|
|
80
|
+
STANDARD_ERROR_CODE = {
|
|
81
|
+
:incorrect_number => 'incorrect_number',
|
|
82
|
+
:invalid_number => 'invalid_number',
|
|
83
|
+
:invalid_expiry_date => 'invalid_expiry_date',
|
|
84
|
+
:invalid_cvc => 'invalid_cvc',
|
|
85
|
+
:expired_card => 'expired_card',
|
|
86
|
+
:incorrect_cvc => 'incorrect_cvc',
|
|
87
|
+
:incorrect_zip => 'incorrect_zip',
|
|
88
|
+
:incorrect_address => 'incorrect_address',
|
|
89
|
+
:card_declined => 'card_declined',
|
|
90
|
+
:processing_error => 'processing_error',
|
|
91
|
+
:call_issuer => 'call_issuer',
|
|
92
|
+
:pickup_card => 'pick_up_card'
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
cattr_reader :implementations
|
|
96
|
+
@@implementations = []
|
|
97
|
+
|
|
98
|
+
def self.inherited(subclass)
|
|
99
|
+
super
|
|
100
|
+
@@implementations << subclass
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def generate_unique_id
|
|
104
|
+
SecureRandom.hex(16)
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
# The format of the amounts used by the gateway
|
|
108
|
+
# :dollars => '12.50'
|
|
109
|
+
# :cents => '1250'
|
|
110
|
+
class_attribute :money_format
|
|
111
|
+
self.money_format = :dollars
|
|
112
|
+
|
|
113
|
+
# The default currency for the transactions if no currency is provided
|
|
114
|
+
class_attribute :default_currency
|
|
115
|
+
|
|
116
|
+
# The supported card types for the gateway
|
|
117
|
+
class_attribute :supported_cardtypes
|
|
118
|
+
self.supported_cardtypes = []
|
|
119
|
+
|
|
120
|
+
class_attribute :homepage_url
|
|
121
|
+
class_attribute :display_name
|
|
122
|
+
|
|
123
|
+
class_attribute :test_url, :live_url
|
|
124
|
+
|
|
125
|
+
class_attribute :abstract_class
|
|
126
|
+
|
|
127
|
+
self.abstract_class = false
|
|
128
|
+
|
|
129
|
+
# The application making the calls to the gateway
|
|
130
|
+
# Useful for things like the PayPal build notation (BN) id fields
|
|
131
|
+
class_attribute :application_id, instance_writer: false
|
|
132
|
+
self.application_id = 'ActiveMerchant'
|
|
133
|
+
|
|
134
|
+
attr_reader :options
|
|
135
|
+
|
|
136
|
+
# Use this method to check if your gateway of interest supports a credit card of some type
|
|
137
|
+
def self.supports?(card_type)
|
|
138
|
+
supported_cardtypes.include?(card_type.to_sym)
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
def self.card_brand(source)
|
|
142
|
+
result = source.respond_to?(:brand) ? source.brand : source.type
|
|
143
|
+
result.to_s.downcase
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
def self.non_fractional_currency?(currency)
|
|
147
|
+
CURRENCIES_WITHOUT_FRACTIONS.include?(currency.to_s)
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
def self.supported_countries=(country_codes)
|
|
151
|
+
country_codes.each do |country_code|
|
|
152
|
+
unless ActiveMerchant::Country.find(country_code)
|
|
153
|
+
raise ActiveMerchant::InvalidCountryCodeError, "No country could be found for the country #{country_code}"
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
@supported_countries = country_codes.dup
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
def self.supported_countries
|
|
160
|
+
@supported_countries ||= []
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
def supported_countries
|
|
164
|
+
self.class.supported_countries
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
def card_brand(source)
|
|
168
|
+
self.class.card_brand(source)
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
# Initialize a new gateway.
|
|
172
|
+
#
|
|
173
|
+
# See the documentation for the gateway you will be using to make sure there are no other
|
|
174
|
+
# required options.
|
|
175
|
+
def initialize(options = {})
|
|
176
|
+
@options = options
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
# Are we running in test mode?
|
|
180
|
+
def test?
|
|
181
|
+
(@options.has_key?(:test) ? @options[:test] : Base.test?)
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
# Does this gateway know how to scrub sensitive information out of HTTP transcripts?
|
|
185
|
+
def supports_scrubbing?
|
|
186
|
+
false
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
def scrub(transcript)
|
|
190
|
+
raise RuntimeError.new("This gateway does not support scrubbing.")
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
protected # :nodoc: all
|
|
194
|
+
|
|
195
|
+
def normalize(field)
|
|
196
|
+
case field
|
|
197
|
+
when "true" then true
|
|
198
|
+
when "false" then false
|
|
199
|
+
when "" then nil
|
|
200
|
+
when "null" then nil
|
|
201
|
+
else field
|
|
202
|
+
end
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
def user_agent
|
|
206
|
+
@@ua ||= JSON.dump({
|
|
207
|
+
:bindings_version => ActiveMerchant::VERSION,
|
|
208
|
+
:lang => 'ruby',
|
|
209
|
+
:lang_version => "#{RUBY_VERSION} p#{RUBY_PATCHLEVEL} (#{RUBY_RELEASE_DATE})",
|
|
210
|
+
:platform => RUBY_PLATFORM,
|
|
211
|
+
:publisher => 'active_merchant'
|
|
212
|
+
})
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
def strip_invalid_xml_chars(xml)
|
|
216
|
+
begin
|
|
217
|
+
REXML::Document.new(xml)
|
|
218
|
+
rescue REXML::ParseException
|
|
219
|
+
xml = xml.gsub(/&(?!(?:[a-z]+|#[0-9]+|x[a-zA-Z0-9]+);)/, '&')
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
xml
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
private # :nodoc: all
|
|
226
|
+
|
|
227
|
+
def name
|
|
228
|
+
self.class.name.scan(/\:\:(\w+)Gateway/).flatten.first
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
def amount(money)
|
|
232
|
+
return nil if money.nil?
|
|
233
|
+
cents = if money.respond_to?(:cents)
|
|
234
|
+
ActiveMerchant.deprecated "Support for Money objects is deprecated and will be removed from a future release of ActiveMerchant. Please use an Integer value in cents"
|
|
235
|
+
money.cents
|
|
236
|
+
else
|
|
237
|
+
money
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
if money.is_a?(String)
|
|
241
|
+
raise ArgumentError, 'money amount must be a positive Integer in cents.'
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
if self.money_format == :cents
|
|
245
|
+
cents.to_s
|
|
246
|
+
else
|
|
247
|
+
sprintf("%.2f", cents.to_f / 100)
|
|
248
|
+
end
|
|
249
|
+
end
|
|
250
|
+
|
|
251
|
+
def localized_amount(money, currency)
|
|
252
|
+
amount = amount(money)
|
|
253
|
+
|
|
254
|
+
return amount unless Gateway.non_fractional_currency?(currency)
|
|
255
|
+
|
|
256
|
+
if self.money_format == :cents
|
|
257
|
+
sprintf("%.0f", amount.to_f / 100)
|
|
258
|
+
else
|
|
259
|
+
amount.split('.').first
|
|
260
|
+
end
|
|
261
|
+
end
|
|
262
|
+
|
|
263
|
+
def currency(money)
|
|
264
|
+
money.respond_to?(:currency) ? money.currency : self.default_currency
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
def truncate(value, max_size)
|
|
268
|
+
return nil unless value
|
|
269
|
+
value.to_s[0, max_size]
|
|
270
|
+
end
|
|
271
|
+
|
|
272
|
+
def requires_start_date_or_issue_number?(credit_card)
|
|
273
|
+
return false if card_brand(credit_card).blank?
|
|
274
|
+
DEBIT_CARDS.include?(card_brand(credit_card).to_sym)
|
|
275
|
+
end
|
|
276
|
+
|
|
277
|
+
def requires!(hash, *params)
|
|
278
|
+
params.each do |param|
|
|
279
|
+
if param.is_a?(Array)
|
|
280
|
+
raise ArgumentError.new("Missing required parameter: #{param.first}") unless hash.has_key?(param.first)
|
|
281
|
+
|
|
282
|
+
valid_options = param[1..-1]
|
|
283
|
+
raise ArgumentError.new("Parameter: #{param.first} must be one of #{valid_options.to_sentence(:words_connector => 'or')}") unless valid_options.include?(hash[param.first])
|
|
284
|
+
else
|
|
285
|
+
raise ArgumentError.new("Missing required parameter: #{param}") unless hash.has_key?(param)
|
|
286
|
+
end
|
|
287
|
+
end
|
|
288
|
+
end
|
|
289
|
+
end
|
|
290
|
+
end
|
|
291
|
+
end
|